MySQL db("localhost", "user", "password", "basename"); MySQL *db = new MySQL("localhost", "user", "password", "basename"); В чем принципиальная разница, кроме того, что в первом случае это объект и выделяется память на стеке локально, а во втором - указатель - память через HeapAlloc? Спрашиваю потому, что в первом случае всё работает нормально, в во втором падает при вызове конструктора: HeapAlloc возвращает ноль. С чем это может быть связано? P.S. Небольшая доп информация: При просмотре в Olly в пошаговом режиме вызов HeapAlloc происходит с нулевым первым параметром. До HeapAlloc другие апи не вызывались (в частности, GetProcessHeap или HeapCreate). Я должен был как-то позаботиться о вызове GetProcessHea, или всё-таки компилятор должен был это сделать?
cresta Ты случайно не отключил CRT? Хотя, странный глюк. Может, malloc? Или ты всё-таки переопределил `new`?
Возможно, что и отключено crt, если ключ /subsystem:windows отключает его. Перекомпилировал с ключом /subsystem:console (было /subsystem:windows) и всё стало на место. На new больше не падает. Это что, /subsystem:console автоматом подключает crt или как? Вот все опции, либы и хидеры: Код (Text): //======================== Options ================ #pragma comment(linker, "/MERGE:.rdata=.text") #pragma comment(linker, "/subsystem:console") //======================== Libraries ============== #pragma comment(lib, "kernel32.lib") #pragma comment(lib, "user32.lib") //======================== Includes =============== #include <windows.h> #include <stdlib.h> #include "mysql.cpp" Если при ключе /subsystem:windows crt был отключен, почему компилятор и линкер не ругались на new и спокойно пропустили его?
Да, entry был переопределен, после добавления ключа subsystem пришлось перейти к традиционному main. Всё понятно, спасибо.
IceStudent Такое впечатление, что ты коллекционируешь ссылки со всего интернета Этакий архивариус ) Но вопрос по HeapAlloc всё равно непонятен. Откуда в файле взялся код, передающий в апи ноль вместо хэндла кучи?
cresta Так вот же ответ: Стандартная библиотека C не инициализировалась, поскольку вместо _tmain запускалась my_main, поэтому и хэндл кучи нулевой.
maxdiver Поставим вопрос несколько иначе: почему в HeapAlloc передается величина, взятая с потолка? Если отключен crt, то часть кода, получающая валидный хэндл кучи, отсутствует (я так понял). Поэтому было бы логично вместо подстановки ерунды вместо хэндла просто выдать некое сообщение об ошибке и заблокировать генерацию заведомо бажного кода. Если к примеру, у нас отсутствует какая-либо библиотека, и мы пытаемся прилинковать код из неё, получаем unresolved symbol. Точно также я ожидал unresolved symbol <кто_там_отвечает_за_выделение_памяти_в_куче> Т.е. пропущена явная ошибка. Или что, использование crt в обязательнои порядке заложено в стандартах, и проверять её наличие не надо???
дык ты то crt не отключил, только entry-point сменил, но все библиотеки грузятся, и если ты юзаешь crt-функции, то они ожидают корректной инициализации.
Значит, кроме подключения, необходима инициализация crt? Которая производится, если используется стандартный entry point.
Это не совсем так: если не используется crt, то strlen, strcpy, stricmp импортируются из ntdll.dll. И работают они не в пример crt-шным аналогам безопасно. Например для crt-функции код int len = strlen(0); вызывает падение программы. Если же strlen импортируется из ntdll, то этот код не вызывает падения программы, и возвращает ноль. Т.е. crt не заботится о том, чтобы передача невалидного параметра не приводила к фатальным последствиям. И вся эта история с оператором new тоже имеет корни в этом. В общем, мое недоверие к crt только возвросло Посему последний вопрос по теме: как переопределить функции - понятно: отключить либу-экспортер и написать свою реализацию. А вот как переопределить оператор new? Даже с отключеной crt получается ошибка: linkage specification contradicts earlier specification for 'operator new' Есть пример такого рода?
В первый раз такое слышу. Насколько я знаю, эти функции (по крайней мере, strlen и strcpy) просто подставляются компилятором, поскольку их ассемблерный код очень мал.
cresta Нет, просто помню, что есть та или иная либа, а ссылки подсказывает гугл. Приведи пример кода. Ты, видимо, пытаешься переопределить с использованием стандартных заголовочных файлов или делаешь это некорректно. Если хочешь со стандартными хидерами - просто сделай определение операторов new и delete без объявления, как в libctiny.
Ну память у тебя неслабая О переопределении: вот как раз я и пытался эту libctiny переделать. Там в ней printf некорректно отображает кириллицу. Всего то надо добавить вызов апи CharToOem. Взял все функции из архива libctiny и переделаную printf, сложил их в один .cpp, и отдал компилятору: libctiny.cpp(420) : error C2732: linkage specification contradicts earlier specification for 'operator new' libctiny.cpp(419) : see declaration of 'operator new' libctiny.cpp(425) : error C2732: linkage specification contradicts earlier specification for 'operator delete' libctiny.cpp(424) : see declaration of 'operator delete' Интересно, как автор компилировал свою либу? Сорец в аттаче, глянь если нетрудно, что там не так. Компилировал батником: cl /c /Gz /LD /Ox libctiny.cpp link /LIB libctiny.obj /out:LIBCTINY.lib Не понял, а где кнопка аттача? Или аттачи отменили? Заслал тебе на личку .cpp
IceStudent Нашел, в чем дело: блок Код (Text): #ifdef __cplusplus extern "C" { #endif тащит за собой старые определения new и delete (видимо откуда-то из crt). Убрал этот блок - и все стало на место. Кроме моих new и delete других больше не существует.
А обычный printf отображает корректно? Обычный тоже некорректен в этом отношении. Но мы не будем на него равняться