Предположим, что m_dArRetX[i] содержит некую переменную типа double. По правилу обработки формат спецификатора %f размер результата может заметно превышать 9 + 1 символ. Таким образом, если sprintf вернет число больше, чем (размер буффера -1), то ты попал Оператор delete[] уже эту память удалить не сможет, а, соответственно, ты получишь какой-нибудь AV.
Здравствуйте Андрей Тарасевич, Вы писали:
АТ>Во-первых, если буферы у тебя известного на стадии компиляции размера, то зачем выделять их в динамисеской памяти? Почему не в автоматической?
Нет буферы не извесны на стадии компиляции.
АТ>В-третих, применение макро '_T' к чему-либо, кроме строкового или символьного литерала — полная бессмыслица.
Вдруг полезут иероглифы.
Далее я периписал и боюсь, что опять не правильно
Здравствуйте Klestov, Вы писали:
K>Какой тип имеет сзачение m_dArRetY[i]. K>1) double : sprintf(bufY,"%lf",m_dArRetY[i]); K>2) float : sprintf(bufY,"%f",m_dArRetY[i]);
Эта рекомендация не имеет никакого смысла:
1) флаг l перед спецификаторами a, A, e, E, f, F, g, или G игнорируется; не игнорируется флаг L, но Lf означает, что аргумент имеет тип long double; просто f означает double (см. ISO/IEC 9899:1999 7.19.6.1/7);
2) аргумент типа float при передаче в функцию с переменным числом параметров всегда преобразуется к double (см. ISO/IEC 14882:1998 п. 5.2.2/7 или ISO/IEC 9899:1999 6.5.2.2/6).
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте gbush, Вы писали:
G>Здравствуйте Андрей Тарасевич, Вы писали:
АТ>>Во-первых, если буферы у тебя известного на стадии компиляции размера, то зачем выделять их в динамисеской памяти? Почему не в автоматической?
G>Нет буферы не извесны на стадии компиляции.
АТ>>В-третих, применение макро '_T' к чему-либо, кроме строкового или символьного литерала — полная бессмыслица. G>Вдруг полезут иероглифы. G>Далее я периписал и боюсь, что опять не правильно
G>
Здравствуйте Klestov, Вы писали:
K> K>char *strbuf = new char;
K>Массив из одного элемента
K>Length = XXX K>char *strbuf = new char [Length];
Да я согласен, что это бред, но почему в ListGrid я вижу полное значение чисел из нескольких символов.
И пожалуйста научите, как выделить память ровно столько, сколько нужно под эти значения чисел. И главное экономно и правильно.
Да и м.б ссылку где указатели хорошо разобраны.
Ничего, что я так?
А при чем здесь delete? В этом случае он получит AV (или int3) еще при попытке sprintf записать в невыделенную память...
Kaa>Предположим, что m_dArRetX[i] содержит некую переменную типа double. По правилу обработки формат спецификатора %f размер результата может заметно превышать 9 + 1 символ. Таким образом, если sprintf вернет число больше, чем (размер буффера -1), то ты попал Оператор delete[] уже эту память удалить не сможет, а, соответственно, ты получишь какой-нибудь AV.
Kaa>
Здравствуйте Andrew S, Вы писали:
AS>А при чем здесь delete? В этом случае он получит AV (или int3) еще при попытке sprintf записать в невыделенную память...
На практике (моей) выяснено, что не получит. Перезапись, как и перечтение — очень коварный зверь, который достаточно трудно бывает отловить. Часто такие примерно рабоатющие куски кода приводят к помешательству программиста, просмотру всех исходников, потому как являются причиной неработоспособности релизной версии (часто, не всегда), при работающей дебажной. При этом перечтения содержатся и там, и там, но и релизная версия при некоторых условиях умудряетс япроезжать (на этой неделе 2 таких поймал ).
Проведи эксперимент, если не веришь. Падение происходит при перечтении/записи (ну, при нежесткой, пару байт, там, 10 байт) часто только при высвобождении памяти. (Ну, я про винду, а не вообще )
На самом деле это сильно зависит от компилятора и виндовс. На 9х можно и килобайтом обшибиться — они не заметят. На 2000-х у меня обычно отлавливается и один байт сразу при записи/чтении... А для пущего удовольствия есть Bounds Checker.
Kaa>Проведи эксперимент, если не веришь. Падение происходит при перечтении/записи (ну, при нежесткой, пару байт, там, 10 байт) часто только при высвобождении памяти. (Ну, я про винду, а не вообще )
Здравствуйте gbush, Вы писали:
G>Здравствуйте Klestov, Вы писали:
K>> K>>char *strbuf = new char;
K>>Массив из одного элемента
K>>Length = XXX K>>char *strbuf = new char [Length]; G>Да я согласен, что это бред, но почему в ListGrid я вижу полное значение чисел из нескольких символов. G>И пожалуйста научите, как выделить память ровно столько, сколько нужно под эти значения чисел. И главное экономно и правильно. G>Да и м.б ссылку где указатели хорошо разобраны. G>Ничего, что я так?
Здравствуйте Andrew S, Вы писали:
AS>А при чем здесь delete? В этом случае он получит AV (или int3) еще при попытке sprintf записать > в невыделенную память...
подобные вещи генерируются, когда получается выход за пределы памяти, с которой работает "железо":
сегменты, страницы. В случае же с new и malloc,alloc etc память выделяется меньшими блоками из
предварительно выделенного бОльшего хипа. В этом случае возможна ситуация, когда произойдет
"перезаписывание" или "наползание" на некоторую рабочую структуру runtime библиотеки или же
на другие данные приложения, но выхода за пределы аппаратно контролируемой памяти не произойдет. Соответственно ошибка вылезет не сразу, а потом, при обращении к "покалеченным" данным
runtime'а (обращение к функциям работы с памятью) или же "покалеченным" данным приложения.
В случае с sprintf память скорее всего уже выделена.
т.е. если написать
char *pc_buffer = new char[ 4 ];
strcpy( pc_buffer, "0123456789" );
delete pc_buffer;
ошибка возникнет не на strcpy, а на delete или еще позже.
немного коряво получилось... но вроде все обстоит именно так
Немного не так. На самом деле в дебаговой версии рантайм делает еще некие телодвижения для проверки правильности использования памяти. Но даже не в этом дело.
А>В случае с sprintf память скорее всего уже выделена. А>т.е. если написать А> char *pc_buffer = new char[ 4 ]; А> strcpy( pc_buffer, "0123456789" ); А> delete pc_buffer; А>ошибка возникнет не на strcpy, а на delete или еще позже.
А вот тут ошибка скорее всего в ДНК — delete должно быть с [].