2015-12-20 2 views
0

Я получаю ошибку сегментации в следующем коде, и я действительно не могу понять, где проблема. Предполагается, что программа содержит динамический массив целых чисел без знака, которые изменяются в функции setBreakPoint. Ошибка сегментации возникает при назначении второго элемента массива (первый работает без проблем).Ошибка сегментации после изменения динамического массива

#include <stdio.h> 
#include <stdlib.h> 

void setBreakPoint(unsigned int **break_points, unsigned int *number_of_break_points, unsigned int new_break_point) 
{ 
    unsigned int *buffer; 
    if(new_break_point > 0) 
    { 
    buffer = realloc(*break_points, ++(*number_of_break_points) * sizeof(unsigned int)); 
    if(buffer != NULL) 
    { 
     *break_points = buffer; 
     *break_points[(*number_of_break_points) - 1] = new_break_point; 
    } 
    } 
    return; 
} 

int main(void) 
{ 
    unsigned int *break_points = NULL; 
    unsigned int number_of_break_points = 0; 

    setBreakPoint(&break_points, &number_of_break_points, 10); 
    setBreakPoint(&break_points, &number_of_break_points, 5); 

    free(break_points); 
    return 0; 
} 

Здесь вывод от valgrind. Всего выделено 12 байт, что кажется вполне законным (4 байта при первом вызове функции и 8 во втором). Насколько я могу судить, кажется, что есть назначение указателю NULL, но я не понимаю, почему.

==8695== Invalid write of size 4 
==8695== at 0x4005BA: setBreakPoint (in /break_points) 
==8695== by 0x400605: main (in /break_points) 
==8695== Address 0x0 is not stack'd, malloc'd or (recently) free'd 
==8695== 
==8695== HEAP SUMMARY: 
==8695==  in use at exit: 8 bytes in 1 blocks 
==8695== total heap usage: 2 allocs, 1 frees, 12 bytes allocated 
==8695== 
==8695== LEAK SUMMARY: 
==8695== definitely lost: 0 bytes in 0 blocks 
==8695== indirectly lost: 0 bytes in 0 blocks 
==8695==  possibly lost: 0 bytes in 0 blocks 
==8695== still reachable: 8 bytes in 1 blocks 
==8695==   suppressed: 0 bytes in 0 blocks 
+1

Назначение результата 'realloc()' первому аргументу, с которым вы вызываете его, всегда является ошибкой. Не делайте этого, потому что это делает невозможным предотвращение утечки ресурсов при возникновении ошибки. –

+0

@Alexguitar, Почему это всегда будет правдой? – donjuedo

+0

@Alexguitar: вызов в главной функции здесь является лишь примером. Его также называют в другом месте, где new_break_point не обязательно должно быть> 0 – lenxn

ответ

2

Проблема заключается в этом выражении:

*break_points[(*number_of_break_points) - 1] 

Оператор индекс [] имеет более высокий приоритет, чем эталонная указатель opeator * так что ваш код разбирает неправильно. Оно должно быть:

(*break_points)[(*number_of_break_points) - 1] 

Любопытно, что вы добавили скобки (*number_of_break_points), где они не нужны.

Самое смешное, что, поскольку вы используете указатель-на-указатель, обе интерпретации *(p[i]) и `` (* p) [i] are valid. Also, when the index value is 0` результирующее значение одно и то же, поэтому при первом запуске но второй терпит неудачу.

PS: Обратите внимание, что у вас есть еще одна ошибка suble: если realloc не работает, вы все равно увеличиваете счетчик. Было бы проще что-то вроде:

buffer = realloc(*break_points, (*number_of_break_points) * sizeof(unsigned int)); 
    if(buffer != NULL) 
    { 
     *break_points = buffer; 
     buffer[(*number_of_break_points)++] = new_break_point; 
    } 
+1

Ты избил меня. Мне нужно научиться печатать быстрее. ;-) – donjuedo

1

Код *break_points[(*number_of_break_points) - 1] не работает, как вы ожидаете. С приоритетом оператора у нас есть значение C, которое оценивается до * (break_points[..]). Вы должны написать `(* break_points) [..].

 Смежные вопросы

  • Нет связанных вопросов^_^