Passando referência ao vetor STL sobre o limite da DLL

Eu tenho uma boa biblioteca para gerenciar arquivos que precisa retornar listas específicas de strings. Como o único código com o qual eu vou usá-lo será C ++ (e Java, mas que está usando C ++ através de JNI), decidi usar o vetor das bibliotecas padrão. As funções da biblioteca se parecem um pouco com isso (onde FILE_MANAGER_EXPORT é um requisito de exportação definido pela plataforma):

extern "C" FILE_MANAGER_EXPORT void get_all_files(vector<string> &files)
{
    files.clear();
    for (vector<file_struct>::iterator i = file_structs.begin(); i != file_structs.end(); ++i)
    {
        files.push_back(i->full_path);
    }
}

O motivo pelo qual eu usei o vetor como referência, em vez do valor de retorno, é uma tentativa de manter as alocações de memória sãs e porque o Windows estava realmente infeliz por eu ter um "C" externo em torno de um tipo de retorno c ++ (quem sabe por quê, meu entendimento é que todos são externos " C "faz é impedir que o nome seja alterado no compilador). De qualquer forma, o código para usá-lo com outros c ++ é geralmente o seguinte:

#if defined _WIN32
    #include <Windows.h>
    #define GET_METHOD GetProcAddress
    #define OPEN_LIBRARY(X) LoadLibrary((LPCSTR)X)
    #define LIBRARY_POINTER_TYPE HMODULE
    #define CLOSE_LIBRARY FreeLibrary
#else
    #include <dlfcn.h>
    #define GET_METHOD dlsym
    #define OPEN_LIBRARY(X) dlopen(X, RTLD_NOW)
    #define LIBRARY_POINTER_TYPE void*
    #define CLOSE_LIBRARY dlclose
#endif

typedef void (*GetAllFilesType)(vector<string> &files);

int main(int argc, char **argv)
{
    LIBRARY_POINTER_TYPE manager = LOAD_LIBRARY("library.dll"); //Just an example, actual name is platform-defined too
    GetAllFilesType get_all_files_pointer = (GetAllFilesType) GET_METHOD(manager, "get_all_files");
    vector<string> files;
    (*get_all_files_pointer)(files);

    // ... Do something with files ...

    return 0;
}

A biblioteca é compilada através do cmake usando add_library (file_manager SHARED file_manager.cpp). O programa é compilado em um projeto cmake separado usando add_executable (file_manager_command_wrapper command_wrapper.cpp). Também não há sinalizadores de compilação especificados, apenas esses comandos.

Agora, o programa funciona perfeitamente bem no mac e no linux. O problema é o Windows. Quando executado, recebo este erro:

Falha na declaração de depuração!

...

Expressão: _pFirstBlock == _pHead

Eu descobri e meio que entendo que isso se deve a pilhas de memória separadas entre executáveis e dlls carregadas. Eu acredito que isso ocorre quando a memória é alocada em um heap e desalocada no outro. O problema é que, para a minha vida, não consigo entender o que está errado. A memória é alocada no executável e passada como referência à função dll, os valores são adicionados por meio da referência e, em seguida, são processados e finalmente desalocados no executável.

Eu revelaria mais código, se pudesse, mas a propriedade intelectual da minha empresa afirma que não, então todo o código acima é apenas exemplos.

Alguém com mais conhecimento do assunto capaz de me ajudar a entender esse erro e me indicar a direção certa para depurar e corrigi-lo? Infelizmente, não sou capaz de usar uma máquina Windows para depuração, pois desenvolvo no Linux, depois cometo quaisquer alterações em um servidor gerrit que aciona compilações e testes através do jenkins. Eu tenho acesso ao console de saída ao compilar e testar.

Eu considerei usar tipos não-stl, copiando o vetor em c ++ para um caractere **, mas a alocação de memória era um pesadelo e eu estava lutando para fazê-lo funcionar muito bem no linux, sem falar nas janelas e é horrível várias pilhas.

EDIT: Definitivamente trava assim que o vetor de arquivos sai do escopo. Meu pensamento atual é que as seqüências de caracteres inseridas no vetor são alocadas no heap dll e desalocadas no heap executável. Se for esse o caso, alguém pode me esclarecer sobre uma solução melhor?

questionAnswers(7)

yourAnswerToTheQuestion