Получить сигнал SIGSEGV при использовании malloc для char * в Linux Qt Creator C++

Когда я запускаю следующий код для выделения памяти для char * с помощью malloc() в QT Linux C++, SIGSEGV сигнализируется примерно после 250 выполнений.

for(int i = 0; i < 10000; i++)
{
   char * test = (char * )malloc(500);
   test = "mas";
   cout<<test<<endl; 
}

Я пытался использовать free() или delete(), но они также запускают системный сигнал.

В чем проблема?


person NickWest    schedule 18.07.2014    source источник


Ответы (5)


Основная проблема заключается в том, что вы наступаете на свой указатель malloc(). Наступая на него несколько раз:

// Original test case
for(int i = 0; i < 10000; i++) {
   char * test = (char * )malloc(500);
   test = "mas";  // BAD!!! 
                  // You've just stepped on your "malloc'ed" pointer with a *different pointer!!!!
   cout<<test<<endl; 
}

Вот альтернатива. Обратите внимание, что у вас также должен быть какой-то способ «запомнить» указатель для каждого malloc(), чтобы вы могли «освободить()» его в нужное время:

// Better:
for(int i = 0; i < 10000; i++) {
   char * test = (char * )malloc(500);
   if (test == NULL) {
     cout <<  "malloc error!" << endl;
     break;
   }
   strcpy (test, "mas");
   cout<<test<<endl; 
   free (test);
}
person FoggyDay    schedule 18.07.2014
comment
Привет, метод free() приводит к сигналу SIGABRT. Как я могу этого избежать? - person NickWest; 19.07.2014
comment
Привет - я добавил (необходимый!) тест для ошибки mallocI). В: На какой платформе вы находитесь? Окна? линукс? В: Какой компилятор вы используете? МСВС? ССЗ? В: Не могли бы вы попробовать запустить код как есть в отладчике? ТАКЖЕ: пожалуйста, посмотрите на ответ Джона Диблинга. Он пытается сказать тебе то же самое, что и я... - person FoggyDay; 20.07.2014
comment
Привет, я на Линукс. Я использую GCC с QT Creator. Я попробовал код, и теперь он работает. разрыва не произошло. Благодарю вас! - person NickWest; 25.07.2014

Вы изменили значение проверки указателя. Вам нужно использовать memcpy или что-то подобное, чтобы скопировать значение «mas» в буфер.

А еще лучше используйте std::string

person Vinbot    schedule 18.07.2014
comment
Привет, я изменил его, но malloc по-прежнему вызывает сигнал SIGSEGV. - person NickWest; 19.07.2014

Этот код:

test = "mas";

Делает не то, что вы думаете. Вы думаете, что он копирует строку "mas" в буфер, на который указывает test. Что он на самом деле делает, так это изменяет то, на что указывает test. Вместо того, чтобы указывать на память, которую вы выделенный с помощью malloc, теперь он указывает на статически выделенный буфер символов.

person John Dibling    schedule 18.07.2014
comment
Благодарю вас! Я изменил код, чтобы использовать strcpy(), и теперь он отлично работает. - person NickWest; 25.07.2014

Когда вы выделяете память с помощью malloc или new, вы получаете взамен только указатель, поэтому вам нужно подходить к этому по-другому - с такими функциями, как strcpy, strcmp (если вам нужно проверить равенство текстов, вы также не можете сравнивать только указатели ). Узнайте больше об указателях в любой книге по C++. Можно создавать тексты без явного выделения памяти, например, это законно:

const char *text = "my text";

Но дальнейшие модификации, как вы показали, не являются (обратите внимание на const, это дает нам больше безопасности). В этом случае текст создается где-то в памяти самим компилятором (сейчас я упрощаю), и назначается только указатель. В этом случае вы не можете изменить этот текст (по крайней мере, небезопасно).

Следующее, когда вы выделяете какую-либо память, вы должны освободить ее вручную, по крайней мере, в таких языках, как C/C++, где управления памятью (сборщики мусора и т. д.) на самом деле не существует. Если вы пропустите этот шаг, вы столкнетесь с проблемами (например, с нехваткой памяти) быстрее, чем вы думаете.

person gecio    schedule 18.07.2014
comment
Привет, спасибо за ответ. Я пытался использовать delete() или free() после предложения cout‹‹, но это все время вызывает SIGBRT. Так что я действительно не знаю, что происходит. - person NickWest; 19.07.2014
comment
Послушайте, я предполагаю, что вы все еще назначаете указатели, как в вопросе. Malloc возвращает вам указатель, он хранится в тесте, затем вы назначаете указатель на mas (хранящийся где-то в программе) той же переменной, когда вы пытаетесь его освободить, вы сталкиваетесь с проблемой, потому что вы не можете изменять и удалять такого рода Память. Используйте для этого такие функции, как strcpy или даже memcpy. Обновите свой вопрос, если вы что-то изменили с ним. Я призываю вас исправить это и не пытаться обойти проблему, потому что ее понимание необходимо в программировании. Удачи. - person gecio; 21.07.2014

это утверждение:

    test = "mas";

копирует не строки, а указатели.

Чтобы скопировать строку в C, используйте осторожно strcpy(3) (часто strncpyлучше).

    strcpy(test, "mas");

Но вам действительно следует использовать (как ответил Vinbot) std::string, так как вы кодируете на C++

Кроме того, компилируйте код C++ в Linux с g++ -g Wall (и код C с gcc -g -Wall), чтобы получать предупреждения и отладочную информацию. Узнайте, как использовать отладчик gdb, а также valgrind.

См. также этот ответ на соответствующий вопрос.

person Basile Starynkevitch    schedule 18.07.2014
comment
Хорошо, я буду использовать строку, похоже, есть проблема с использованием malloc - person NickWest; 19.07.2014
comment
Нет проблем с использованием malloc, но у вас есть временная проблема с пониманием того, что такое указатели и строки. Это нормально, указатель — сложная концепция. Так что найдите время, чтобы прочитать об этом! - person Basile Starynkevitch; 19.07.2014
comment
Благодарю вас! Я изменил все в Char* на строку. Теперь все идет хорошо. malloc действительно вызывает SIGSEGV через некоторое время, около 250 раз, для char *. Я до сих пор не знаю, почему. - person NickWest; 19.07.2014