выделение и освобождение символа * в c ++ - PullRequest
0 голосов
/ 25 мая 2009

Привет всем, я получаю ошибку повреждения кучи, которую я не могу понять.

char * c = (char *) malloc(1);
// main loop
_gcvt_s(c, 100, ball->get_X_Direction(), 10);
      if(pushFont(c, (SCREEN_WIDTH - 30), (SCREEN_HEIGHT - 40), message, screen,
font, textColor) == false)
      {
           //return 1; // error rendering text.
      }
// end main loop
free(c);

Приведенный выше код - единственный раз, когда я использую указатель c в _gcvt_s и pushFont (), который просто принимает char * в качестве первого параметра и выводит текст на экран. Другое то, что я не использую c. Когда я пытаюсь освободить c после основного цикла (что, я думаю, я должен сделать), я получаю сообщение об ошибке, в котором говорится, что Visual Studio получила ошибку с кучей (повреждение кучи).

Комментируя вызов pushFont, я все еще получаю сообщение об ошибке.

Может кто-нибудь объяснить мне, почему освобождение символа (1 байт, который я выделил в куче) может привести к повреждению кучи?

Наконец, мой основной цикл делает много вещей, приятель, и я создаю игру в понг с WinSocket, остальная часть основного корпуса - цикл для игры. Я не думал, что это нужно было публиковать, но я буду обновлять свой пост всем основным циклом, если это необходимо, но я думаю, что я просто не согласен с моим пониманием malloc () и free ().

Спасибо всем,

Ответы [ 4 ]

9 голосов
/ 25 мая 2009

Разве _gcvt_s не использует 2-й параметр в качестве максимального размера выделенного буфера? Вы выделяете 1 байт, но сообщаете _gcvt_s, что их 100. Таким образом, он успешно записывает до 100 байт в буфер, повреждая вашу кучу. Тогда бесплатно вылетает. Выделите 100 байт, если вы собираетесь получить доступ к 100 байтам.

РЕДАКТИРОВАТЬ: Похоже, вам нужно узнать, как С хранит и манипулирует строками. C хранит строки как отдельные байты в последовательных запусках памяти, за которыми следует дополнительный символ, обозначающий конец строки. Этот дополнительный символ имеет значение ASCII 0 (не символ «0», который является ASCII 48). Поэтому, если у вас есть строка типа «HELLO», для ее хранения требуется 6 байтов - по одному на каждую из 5 букв и терминатор.

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

Согласно этой [документации] (http://msdn.microsoft.com/en-us/library/a2a85fh5(VS.80).aspx), в заголовках есть #define для максимально необходимого размера буфера: _CVTBUFSIZE. Приведенный здесь пример должен помочь вам в этом.

4 голосов
/ 25 мая 2009

Согласно документации, которую я могу найти _gcvt_s() принимает буфер и длину этого буфера в качестве первых двух аргументов.

errno_t _gcvt_s( 
   char *buffer,
   size_t sizeInBytes,
   double value,
   int digits 
);

Ваш malloc() буфер ed имеет длину 1 байт, вы говорите _gcvt_s(), что он имеет длину 100 байт. Я бы начал искать здесь.

3 голосов
/ 25 мая 2009

Зачем вам нужна куча? Если все, что вам нужно, это место для 1 символа, вы не можете просто использовать локальную переменную:

char c;
_gcvt_s(&c...

1 голос
/ 25 мая 2009

Вам нужно более одного байта для хранения числа с плавающей запятой. Выделите более практичную длину, чем 1 байт ...

Вам также действительно не нужна куча, попробуйте (немного увеличенный) 16-байтовый буфер и задайте _gcvt_s правильную длину буфера (вместо магических 100, которые вы даете). Размагируйте ваши константы, пока вы в нем.

const unsigned int cuFloatStringLength = 16;
const unsigned int cuFloatStringPrecision = 10;

char c[cuFloatStringLength];

_gcvt_s( c, cuFloatStringLength, ball->get_X_Direction(), cuFloatStringPrecision );

Проблема должна исчезнуть.

...