2016-01-29 6 views
0

У меня возникла проблема с функцией, которая объединяет число до конца массива символов. Я честно не могу видеть проблему:Ошибка кучи повреждения в Visual Studio при освобождении динамической памяти

void x(int num, char* originalArray) { 

    char* concat_str = new char[1]; 
    sprintf(concat_str, "%d", num); 

    for (int i = 0; i < 1; i++) 
     originalArray[i + 10] = concat_str[i]; 

    delete [] concat_str; 
    } 

Сообщение об ошибке:

КУЧА КОРРУПЦИЯ ОБНАРУЖЕН: после нормального блока (# 147) на 0x01204CA0. CRT обнаружил, что приложение записано в память после окончания буфера кучи.

Любые идеи? Я начинающий программист, но я много раз делал то же самое и никогда не сталкивался с этой проблемой. Благодарю.

+1

** символ * concat_str = новый символ [1]; ** Вы понимаете, в CString размера 1 может содержать только нулевой завершающий символ. Любые цифры числа будут слишком большими. – drescherjm

+1

* но я много раз делал то же самое и никогда не сталкивался с этой проблемой. * - Ты много раз попирал память и не имел проблемы?Возможно, вам стоит просмотреть свой старый код, так как выполнение того, что вы делаете в сообщении, - это неопределенное поведение. – PaulMcKenzie

+2

Зачем даже беспокоиться о новых и удалять там? Просто объявите буфер в стеке, например 'concat_str [32];'. –

ответ

4

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

+0

А нуль-терминатор. Я сделал размер массива еще больше, чем должен, и он сработал. Благодаря! – jshapy8

+2

@ revolution9540 Почему только еще один? Нет необходимости находиться на краю ножа. Убедитесь, что у вас достаточно места, делая массив больше, чем вы ожидаете. – PaulMcKenzie

+0

@PaulMcKenzie Я просто стараюсь быть как можно более эффективным, полагаю? Если я точно знаю, что будет храниться в массиве, почему было бы неплохо сделать его больше, чем нужно? – jshapy8

1

Вы выделяете один байт для concat_str и sprintf'ing то, что требует больше места, чем это.

+0

Также неясно, перехватываете ли вы все, что передается буфером initialArray. Для этого также должна быть какая-то проверка. –

1

Прежде всего, обратите внимание, что ваш API является C api. Если вам нужен динамический массив на C++, используйте std::vector<char>.

Но, полагая, что вам нужно придерживаться API C, нет никакого способа гарантировать, что ваш originalArray достаточно велик, чтобы сохранить результат. Кроме того, временный буфер не нужен.

Вы должны изменить API и реализацию следующим образом:

  1. Возьмите размер назначения, чтобы гарантировать, что он не запишет мимо конца.

  2. Запишите строку в буфер назначения. Ввод его во временный буфер, а затем копирование в пункт назначения - пустая трата времени.

  3. snprintf, а не sprintf. Последнее небезопасно: вы не можете гарантировать, что он не будет писать мимо конца вашего буфера.

  4. Вы должны подтвердить предположение, что смещение, по меньшей мере, меньше размера адресата.

    Если предварительное условие выполнено, назначение всегда будет иметь нулевое завершение, хотя текстовое представление num может не соответствовать ему.

  5. Вы можете вернуть длину места назначения, необходимое для соответствия значения.

Таким образом:

size_t fun(int num, char * dest, size_t dest_size) { 
    const size_t offset = 10; 
    assert(dest_size > offset); 
    return offset + snprintf(dest + offset, dest_size - offset, "%d", num); 
} 
Смежные вопросы