Инициализация класса

Тема в разделе "LANGS.C", создана пользователем cresta, 1 сен 2007.

  1. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    MySQL db("localhost", "user", "password", "basename");
    MySQL *db = new MySQL("localhost", "user", "password", "basename");

    В чем принципиальная разница, кроме того, что в первом случае это объект и выделяется память на стеке локально, а во втором - указатель - память через HeapAlloc?
    Спрашиваю потому, что в первом случае всё работает нормально, в во втором падает при вызове конструктора: HeapAlloc возвращает ноль.
    С чем это может быть связано?

    P.S.

    Небольшая доп информация: При просмотре в Olly в пошаговом режиме вызов HeapAlloc происходит с нулевым первым параметром. До HeapAlloc другие апи не вызывались (в частности, GetProcessHeap или HeapCreate).

    Я должен был как-то позаботиться о вызове GetProcessHea, или всё-таки компилятор должен был это сделать?
     
  2. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    cresta
    Ты случайно не отключил CRT? Хотя, странный глюк.

    Может, malloc? Или ты всё-таки переопределил `new`?
     
  3. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Возможно, что и отключено crt, если ключ /subsystem:windows отключает его. Перекомпилировал с ключом /subsystem:console (было /subsystem:windows) и всё стало на место. На new больше не падает. Это что, /subsystem:console автоматом подключает crt или как?

    Вот все опции, либы и хидеры:
    Код (Text):
    1. //======================== Options ================
    2.     #pragma comment(linker, "/MERGE:.rdata=.text")
    3.     #pragma comment(linker, "/subsystem:console")
    4.  
    5. //======================== Libraries ==============
    6.     #pragma comment(lib, "kernel32.lib")
    7.     #pragma comment(lib, "user32.lib")
    8.  
    9. //======================== Includes ===============
    10.     #include     <windows.h>
    11.     #include     <stdlib.h>
    12.     #include    "mysql.cpp"
    Если при ключе /subsystem:windows crt был отключен, почему компилятор и линкер не ругались на new и спокойно пропустили его?
     
  4. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Нет, subsystem здесь не при чём. CRT отключается через /link /nodefaultlib или /link /entry:MyEntry
     
  5. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Да, entry был переопределен, после добавления ключа subsystem пришлось перейти к традиционному main.
    Всё понятно, спасибо.
     
  6. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    cresta
    libctiny тебе поможет, или её производные.
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    IceStudent
    Такое впечатление, что ты коллекционируешь ссылки со всего интернета :) Этакий архивариус :))

    Но вопрос по HeapAlloc всё равно непонятен. Откуда в файле взялся код, передающий в апи ноль вместо хэндла кучи?
     
  8. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    cresta
    Так вот же ответ:
    Стандартная библиотека C не инициализировалась, поскольку вместо _tmain запускалась my_main, поэтому и хэндл кучи нулевой.
     
  9. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    maxdiver

    Поставим вопрос несколько иначе: почему в HeapAlloc передается величина, взятая с потолка?
    Если отключен crt, то часть кода, получающая валидный хэндл кучи, отсутствует (я так понял). Поэтому было бы логично вместо подстановки ерунды вместо хэндла просто выдать некое сообщение об ошибке и заблокировать генерацию заведомо бажного кода.
    Если к примеру, у нас отсутствует какая-либо библиотека, и мы пытаемся прилинковать код из неё, получаем unresolved symbol.
    Точно также я ожидал unresolved symbol <кто_там_отвечает_за_выделение_памяти_в_куче>
    Т.е. пропущена явная ошибка. Или что, использование crt в обязательнои порядке заложено в стандартах, и проверять её наличие не надо???
     
  10. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    дык ты то crt не отключил, только entry-point сменил, но все библиотеки грузятся, и если ты юзаешь crt-функции, то они ожидают корректной инициализации.
     
  11. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Значит, кроме подключения, необходима инициализация crt? Которая производится, если используется стандартный entry point.
     
  12. CnCVK

    CnCVK New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2006
    Сообщения:
    108
    да, если хочешь использовать все CRT функции.
    (но например strlen, strcpy, stricmp не требуют)
     
  13. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Это не совсем так: если не используется crt, то strlen, strcpy, stricmp импортируются из ntdll.dll.
    И работают они не в пример crt-шным аналогам безопасно.
    Например для crt-функции код int len = strlen(0); вызывает падение программы. Если же strlen импортируется из ntdll, то этот код не вызывает падения программы, и возвращает ноль.
    Т.е. crt не заботится о том, чтобы передача невалидного параметра не приводила к фатальным последствиям.
    И вся эта история с оператором new тоже имеет корни в этом.
    В общем, мое недоверие к crt только возвросло :dntknw:

    Посему последний вопрос по теме: как переопределить функции - понятно: отключить либу-экспортер и написать свою реализацию. А вот как переопределить оператор new? Даже с отключеной crt получается ошибка: linkage specification contradicts earlier specification for 'operator new'
    Есть пример такого рода?
     
  14. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    В первый раз такое слышу. Насколько я знаю, эти функции (по крайней мере, strlen и strcpy) просто подставляются компилятором, поскольку их ассемблерный код очень мал.
     
  15. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    cresta
    Нет, просто помню, что есть та или иная либа, а ссылки подсказывает гугл.

    Приведи пример кода. Ты, видимо, пытаешься переопределить с использованием стандартных заголовочных файлов или делаешь это некорректно. Если хочешь со стандартными хидерами - просто сделай определение операторов new и delete без объявления, как в libctiny.
     
  16. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Ну память у тебя неслабая :)

    О переопределении: вот как раз я и пытался эту 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
     
  17. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    IceStudent

    Нашел, в чем дело: блок
    Код (Text):
    1. #ifdef __cplusplus
    2.   extern "C" {
    3. #endif
    тащит за собой старые определения new и delete (видимо откуда-то из crt). Убрал этот блок - и все стало на место. Кроме моих new и delete других больше не существует.
     
  18. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    А обычный printf отображает корректно?
     
  19. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Правильно, ведь в С нет операторов new/delete.
     
  20. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    А обычный printf отображает корректно?

    Обычный тоже некорректен в этом отношении. Но мы не будем на него равняться :)