英文:
Golang CGO with large char pointer - SEGSERV
问题
我有大量的数据从TagLib库中读取,并传递给GoLang(mpeg图像数据)。
这是获取数据的地方:
void audiotags_mpeg_artwork(TagLib::MPEG::File *mpegFile, int id) {
TagLib::ID3v2::Tag *id3v2 = mpegFile->ID3v2Tag(false);
if (id3v2!=nullptr) {
const TagLib::ID3v2::FrameList frameList = id3v2->frameListMap()["APIC"];
for(auto it = frameList.begin(); it != frameList.end(); it++) {
TagLib::ID3v2::AttachedPictureFrame * frame = (TagLib::ID3v2::AttachedPictureFrame *)(*it);
if (frame!=nullptr && frame->size() > 0) {
const auto &apicBase64 = frame->picture().toBase64();
auto len = apicBase64.size();
if (len > 0) {
// Generate memory for key
char* key = new char[5];
memcpy(key, "APIC", 4);
key[4]='void audiotags_mpeg_artwork(TagLib::MPEG::File *mpegFile, int id) {
TagLib::ID3v2::Tag *id3v2 = mpegFile->ID3v2Tag(false);
if (id3v2!=nullptr) {
const TagLib::ID3v2::FrameList frameList = id3v2->frameListMap()["APIC"];
for(auto it = frameList.begin(); it != frameList.end(); it++) {
TagLib::ID3v2::AttachedPictureFrame * frame = (TagLib::ID3v2::AttachedPictureFrame *)(*it);
if (frame!=nullptr && frame->size() > 0) {
const auto &apicBase64 = frame->picture().toBase64();
auto len = apicBase64.size();
if (len > 0) {
// Generate memory for key
char* key = new char[5];
memcpy(key, "APIC", 4);
key[4]='\0';
// Generate memory for picture data
char* val = new char[len];
memcpy (val, apicBase64.data(), len);
// Send to GoLang
go_map_audiotags(id, key, val);
// Free memory
delete[] key;
delete[] val;
}
}
}
}
}
';
// Generate memory for picture data
char* val = new char[len];
memcpy (val, apicBase64.data(), len);
// Send to GoLang
go_map_audiotags(id, key, val);
// Free memory
delete[] key;
delete[] val;
}
}
}
}
}
在这一点上,go_map_autotags
起作用(我对其他数据使用类似的方法)。这对于其他图片数据也起作用,但是根据大小的不同,会导致崩溃:
unexpected fault address 0x766a000
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x1 addr=0x766a000 pc=0x404530b]
在GoLang中,我有以下导出函数:
//export go_map_audiotags
func go_map_audiotags(id C.int, key *C.char, val *C.char) {
m := maps[int(id)]
k := strings.ToLower(C.GoString(key))
log.Println("go_map_audiotags k:", k) // <--- works
v := C.GoString(val) // <--- crashes
log.Println("go_map_audiotags v:", v) // <--- Does not reach
m[k] = v
}
有没有更好的方法来传输这些数据?我猜测发生的情况是:
- 达到了C.char的限制
- C++由于某种原因在设置GoLang中的v之前回收了内存
英文:
I have a large amount of data being read from TagLib library and passed to GoLang (mpeg image data).
Here is where data is fetched:
void audiotags_mpeg_artwork(TagLib::MPEG::File *mpegFile, int id) {
TagLib::ID3v2::Tag *id3v2 = mpegFile->ID3v2Tag(false);
if (id3v2!=nullptr) {
const TagLib::ID3v2::FrameList frameList = id3v2->frameListMap()["APIC"];
for(auto it = frameList.begin(); it != frameList.end(); it++) {
TagLib::ID3v2::AttachedPictureFrame * frame = (TagLib::ID3v2::AttachedPictureFrame *)(*it);
if (frame!=nullptr && frame->size() > 0) {
const auto &apicBase64 = frame->picture().toBase64();
auto len = apicBase64.size();
if (len > 0) {
// Generate memory for key
char* key = new char[5];
memcpy(key, "APIC", 4);
key[4]='void audiotags_mpeg_artwork(TagLib::MPEG::File *mpegFile, int id) {
TagLib::ID3v2::Tag *id3v2 = mpegFile->ID3v2Tag(false);
if (id3v2!=nullptr) {
const TagLib::ID3v2::FrameList frameList = id3v2->frameListMap()["APIC"];
for(auto it = frameList.begin(); it != frameList.end(); it++) {
TagLib::ID3v2::AttachedPictureFrame * frame = (TagLib::ID3v2::AttachedPictureFrame *)(*it);
if (frame!=nullptr && frame->size() > 0) {
const auto &apicBase64 = frame->picture().toBase64();
auto len = apicBase64.size();
if (len > 0) {
// Generate memory for key
char* key = new char[5];
memcpy(key, "APIC", 4);
key[4]='\0';
// Generate memory for picture data
char* val = new char[len];
memcpy (val, apicBase64.data(), len);
// Send to GoLang
go_map_audiotags(id, key, val);
// Free memory
delete[] key;
delete[] val;
}
}
}
}
}
';
// Generate memory for picture data
char* val = new char[len];
memcpy (val, apicBase64.data(), len);
// Send to GoLang
go_map_audiotags(id, key, val);
// Free memory
delete[] key;
delete[] val;
}
}
}
}
}
At this point, go_map_autotags works (I use a similar method for other data). This also works for other picture data, however depending on the size this will crash with:
> unexpected fault address 0x766a000
> fatal error: fault
> [signal SIGSEGV: segmentation violation code=0x1 addr=0x766a000 pc=0x404530b]
Within GoLang, I have the following export:
//export go_map_audiotags
func go_map_audiotags(id C.int, key *C.char, val *C.char) {
m := maps[int(id)]
k := strings.ToLower(C.GoString(key))
log.Println("go_map_audiotags k:", k) // <--- works
v := C.GoString(val) // <--- crashes
log.Println("go_map_audiotags v:", v) // <--- Does not reach
m[k] = v
}
Is there a bette way I should be transporting this data? I assume what's happening is:
- The C.char limit be being reached
- C++ is, for some reason, recycling the memory before setting v in GoLang
答案1
得分: 1
在你的C代码中,val
中存储的数据没有以空字符结尾。当你使用memcpy
进行复制时,没有包含空字符终止符。在C代码中,将代码更改为:
// 为图片数据生成内存
char* val = new char[len+1];
memcpy(val, apicBase64.data(), len);
val[len] = '// 为图片数据生成内存
char* val = new char[len+1];
memcpy(val, apicBase64.data(), len);
val[len] = '\0';
';
英文:
The data stored in val
is not null-terminated. In your C code, when you make a copy using memcpy
, the null terminator is not included. In the C code, change the code to:
// Generate memory for picture data
char* val = new char[len+1];
memcpy (val, apicBase64.data(), len);
val[len] = '// Generate memory for picture data
char* val = new char[len+1];
memcpy (val, apicBase64.data(), len);
val[len] = '\0';
';
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论