Когда я возвращаю value
абстрактного вида, содержащего вектор из одной FFI, и перебираю его в другой FFI, возникает исключение по завершении второго вызова FFI.Я могу получить доступ к элементам вектора один за другим без проблем, но итерации по значениям, похоже, вызывают проблемы.Не имеет значения, использую ли я для каждого цикла, итератора или даже цикла для индексов.
Код Haxe:
class VectorExample {
public static function main() {
var vec = createVec();
// dumpForIntIter(vec); // fails on exit
dumpEach(vec); // works
}
private static var createVec = neko.Lib.load("vectorLib", "createVec", 0);
private static var dumpForIntIter = neko.Lib.load("vectorLib", "dumpForIntIter", 1);
private static var dumpEach = neko.Lib.load("vectorLib", "dumpEach", 1);
}
Код Cpp:
#include <iostream>
#include <string>
#include <vector>
#include <neko.h>
void free_vec( value handle ) {
std::cout << "freeing vec" << std::endl;
std::vector<std::string>* vec = (std::vector<std::string>*) val_data(handle);
delete vec;
}
DEFINE_KIND(k_vector);
value createVec() {
auto vec = new std::vector<std::string>();
vec->push_back(std::string("one"));
vec->push_back(std::string("two"));
vec->push_back(std::string("three"));
value handle = alloc_abstract(k_vector, vec);
val_gc(handle, free_vec);
return handle;
}
DEFINE_PRIM(createVec,0);
// fails on exit
void dumpForIntIter( value handle ) {
auto vec = (std::vector<std::string>*) val_data(handle);
std::cout << "size: " << vec->size() << std::endl;
for (int ii=0; ii<vec->size(); ii++)
std::cout << " item: " << vec->at(ii) << std::endl;
}
DEFINE_PRIM(dumpForIntIter,1);
// works
void dumpEach( value handle ) {
int ii = 0;
auto vec = (std::vector<std::string>*) val_data(handle);
std::cout << "size: " << vec->size() << std::endl;
std::cout << " item: " << vec->at(0) << std::endl;
ii++;
std::cout << " item: " << vec->at(1) << std::endl;
ii++;
std::cout << " item: " << vec->at(2) << std::endl;
ii++;
}
DEFINE_PRIM(dumpEach,1);
Команда для сборки модуля Neko:
g++ -o vectorLib.ndll -shared -fPIC -std=c++11 -I/usr/include/x86_64-linux-gnu \
-L/usr/lib/x86_64-linux-gnu -lneko -ldl vectorLib.cpp
Вывод при работе с dumpForIntIter
:
size: 3
item: one
item: two
item: three
freeing vec
Called from ? line 1
Called from VectorExample.hx line 6
Uncaught exception - vectorLib@dumpForIntIter
Обратите внимание, что, хотя freeing vec
является последней вещью в журнале,проблема возникает, даже если free_vec
пусто или не существует.
Поскольку dumpForIntIter
и dumpForEach
кажутся мне в основном эквивалентными, я подозреваю, что проблема в createVec
.
Документы: Neko FFI
ОБНОВЛЕНИЕ:
Я отключил перехват исключений в nekovm и обнаружил, что проблема связана с ошибкой сегмента.Это вывод из valgrind:
Jump to the invalid address stated on the next line
at 0x2A50DA10C1C9AED6: ???
Address 0x2a50da10c1c9aed6 is not stack'd, malloc'd or (recently) free'd
Can't extend stack to 0x2a50da10c1c99f88 during signal delivery for thread 1:
no stack segment
Process terminating with default action of signal 11 (SIGSEGV)
Access not within mapped region at address 0x2A50DA10C1C99F88
at 0x2A50DA10C1C9AED6: ???
ОБНОВЛЕНИЕ 2:
Если я изменю vector<string>
на vector<int>
, проблема не исчезнет.Если я перейду на char**
(используя malloc
или new
), проблем не будет.Если я перейду на string
, проблем не будет.Похоже, alloc_abstract
не нравится vector
.