Re[11]: Re: возврат vector<My_Struct> из функции в .dll
От: Rakafon Украина http://rakafon.blogspot.com/
Дата: 29.07.09 00:56
Оценка:
Здравствуйте, Аноним, Вы писали:

А>а я и написал, что линкуется с /MTd или надо обязательно собирать с /MD?

А>со статической линковкой не подходит что-ли ?

Вот что пишет Джефри Рихтер по этому поводу:

Важно понимать, что единое адресное пространство состоит из одного исполняемого модуля и нескольких DLL-модулей. Одни из них могут быть скомпонованы со статически подключаемой библиотекой С/C++, другие — с DLL-версией той же библиотеки, а третьи (написанные не на С/C++) вообще ею не пользуются. Многие разработчики допускают ошибку, забывая, что в одном адресном пространстве может одновременно находиться несколько библиотек С/C++. Взгляните на этот код:

VOID EXEFunc()
{ 
    PVOID pv = DLLFunc(); 

    // обращаемся к памяти, на которую указывает pv;
    // предполагаем, что pv находится в С/C++-куче EXE-файла

    free(pv); 
} 

PVOID DLLFunc()
{
    // выделяем блок в С/C++-куче DLL
    return(malloc(100)); 
}

Ну и что Вы думаете? Будет ли этот код правильно работать? Освободит ли EXE-функция блок, выделенный DLL-функцией? Ответы на все вопросы одинаковы — может быть. Для точных ответов информации слишком мало. Если оба модуля (EXE и DLL) скомпонованы с DLL-версией библиотеки С/C++, код будет работать совершенно нормально. По если хотя бы один из модулей связан со статической библиотекой С/C++, вызов free окажется неудачным. Я не раз видел, как разработчики обжигались на подобном коде.

На самом деле проблема, решается очень просто, если в модуле есть функция, выделяющая память, в нем обязательно должна быть и противоположная функция, которая освобождает память. Давайте-ка перепишем предыдущий код так:
VOID EXEFunc()
{ 
    PVOID pv = DLLFunc();

    // обращаемся к памяти, на которую указывает pv,

    // не делаем никаких предположений по поводу С/C++-кучи
    DLLFreeFunc(pv); 
}

PVOID DllFunc()
{ 
    // выделяем блок в С/C++-куче DLL
    PVOID pv = malloc(100);
    return(pv); 
}

BOOL DLLFreeFunc(PVOID pv)
{ 
    // освобождаем блок, выделенный в С/C++-куче DLL
    return(free(pv)); 
}

Этот код будет работать при любых обстоятельствах. Создавая свой модуль, не забывайте, что функции других модулей могут быть написаны на других языках, а значит, и ничего не знать о malloc и free. Не стройте свой код на подобных допущениях. Кстати, то же относится и к C++-операторам new и delete, реализованным с использованием malloc — free.


Вывод:
... либо возись с экспортированием функций, выделяющих и освобождающих память, либо линкуйся с С++ библиотекой динамически. Если проект пишется исключительно на С++ и состоит из нескольких PE-файлов, то второй способ избавляет от любого подобного геморроя ... вот только redist придётся поставлять вместе с твоим софтом, но это мелочь по сравнению с преимуществами динамической линковки с С++ библиотекой.
:)
"Дайте мне возможность выпускать и контролировать деньги в государстве и – мне нет дела до того, кто пишет его законы." (c) Мейер Ансельм Ротшильд , банкир.
DLL
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.