Golang CGO使用大型字符指针-SEGSERV

huangapple go评论150阅读模式
英文:

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
}

有没有更好的方法来传输这些数据?我猜测发生的情况是:

  1. 达到了C.char的限制
  2. 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-&gt;ID3v2Tag(false);
    if (id3v2!=nullptr) {
        const TagLib::ID3v2::FrameList frameList = id3v2-&gt;frameListMap()[&quot;APIC&quot;];
        for(auto it = frameList.begin(); it != frameList.end(); it++) {
            TagLib::ID3v2::AttachedPictureFrame * frame = (TagLib::ID3v2::AttachedPictureFrame *)(*it);
            if (frame!=nullptr &amp;&amp; frame-&gt;size() &gt; 0) {
                const auto &amp;apicBase64 = frame-&gt;picture().toBase64();
                auto len = apicBase64.size();
                if (len &gt; 0) {
                    // Generate memory for key
                    char* key = new char[5];
                    memcpy(key, &quot;APIC&quot;, 4);
                    key[4]=&#39;
void audiotags_mpeg_artwork(TagLib::MPEG::File *mpegFile, int id) {
TagLib::ID3v2::Tag *id3v2 = mpegFile-&gt;ID3v2Tag(false);
if (id3v2!=nullptr) {
const TagLib::ID3v2::FrameList frameList = id3v2-&gt;frameListMap()[&quot;APIC&quot;];
for(auto it = frameList.begin(); it != frameList.end(); it++) {
TagLib::ID3v2::AttachedPictureFrame * frame = (TagLib::ID3v2::AttachedPictureFrame *)(*it);
if (frame!=nullptr &amp;&amp; frame-&gt;size() &gt; 0) {
const auto &amp;apicBase64 = frame-&gt;picture().toBase64();
auto len = apicBase64.size();
if (len &gt; 0) {
// Generate memory for key
char* key = new char[5];
memcpy(key, &quot;APIC&quot;, 4);
key[4]=&#39;\0&#39;;
// 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;
}
}
}
}
}
&#39;; // 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(&quot;go_map_audiotags k:&quot;, k) // &lt;--- works
	v := C.GoString(val) // &lt;--- crashes
    log.Println(&quot;go_map_audiotags v:&quot;, v) // &lt;--- Does not reach
	m[k] = v
}

Is there a bette way I should be transporting this data? I assume what's happening is:

  1. The C.char limit be being reached
  2. 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] = &#39;
// Generate memory for picture data
char* val = new char[len+1];
memcpy (val, apicBase64.data(), len);
val[len] = &#39;\0&#39;;
&#39;;

huangapple
  • 本文由 发表于 2017年8月26日 06:39:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/45890244.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定