【发布时间】:2020-05-16 02:37:04
【问题描述】:
我刚刚注意到我无法让函数返回结构。
我在启用线程的 ARM32/debian docker 映像上运行它。
这是给我运行时错误的函数:
struct CEC_call des_CEC_call(char * buffy){
char request = buffy[0]; // fails here
buffy+=4;
char obligation = buffy[1];
buffy+=4;
struct CEC_call ceccall;
pepcall.request = request;
pepcall.obligation = obligation;
return ceccall;
}
但是如果我把返回类型改成void,运行就没有问题了:
void des_CEC_call(char * buffy){
char request = buffy[0]; // doesn't fail here
buffy+=4;
char obligation = buffy[1];
buffy+=4;
struct CEC_call ceccall;
pepcall.request = request;
pepcall.obligation = obligation;
}
Return 也适用于任何标准返回类型。
定义结构的标头包含在带有函数的文件中,尽管即使结构定义在同一个文件中,它仍然会崩溃。不知道如何进行调试,任何帮助表示赞赏。
编辑:
更多细节,基于 cmets 的建议:
我已经在我的 mac 以及其他一些带有 docker 的非 arm 架构上重新运行了相同的程序,并且它运行时没有任何明显的问题。与位移有关的某些方面与预期的略有不同,但没有因分段错误而导致运行时错误。我尝试使用各种优化级别运行它,但无济于事。
我以前使用过 GDB,所以我认为这可能会提供一些见解,遗憾的是我无法让它在这个容器上工作。
我确保 GDB 已安装并使用 -0g 重新编译二进制文件。
我用--cap-add=SYS_PTRACE 和--security-opt seccomp=unconfined 运行docker。
每次我得到:
warning: Could not trace the inferior process.
Error:
warning: ptrace: Function not implemented
During startup program exited with code 127.
我可以将 GDB 与其他非 arm、非 32 位 docker 映像一起使用,而不会出现任何问题。我认为这对于另一个问题来说已经足够了,因为我花了很长时间试图让 GDB 与那个环境一起工作。
我真的不知道如何验证,但我已经打印出了buffy指向的地址和buffy[0]在前面的函数中持有的值以及有问题的函数。
没有结构返回:
address of buffy = 0xff58b9ec
buffer[0] = ff
address of buffy = 0xff58b9ec
buffer[0] = ff
address of buffy = 0xff58b9ec
buffer[0] = ff
带结构返回:
address of buffy = 0xff58b9ec
buffer[0] = ff
address of buffy = 0xff58b9ec
buffer[0] = ff
address of buffy = (nil)
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
结构CEC_call 没有任何其他字段。
它可能是某处的缓冲区溢出,但至少没有我制作的任何缓冲区。我以前没有使用过 QEMU IIRC 或 valingrad,但会更详细地研究它们。我目前无法进行原生测试,因为我无法访问预期的嵌入式 linux。
【问题讨论】:
-
是的,不会,粘贴时出错。
-
您是否尝试过在调试器中捕获崩溃?应该可以使用 QEmu IIRC。也许这是代码其他部分中某些未定义行为的原因?也许您在某处有缓冲区溢出?考虑到您的目标操作系统是 Debian(即 Linux),那么您应该能够本地构建代码(在主机上和主机上)并使用类似 Valgrind 的东西来检查问题。
-
尝试禁用优化并重新编译第二个代码。
-
当您将返回值替换为
void时,编译器可能会通过删除其中的大部分代码来显着优化函数,因为它变得无用了。删除的代码可能包含导致错误的代码。关于错误的可能原因,我认为它可能是堆栈溢出引起的(局部变量也分配在堆栈上),但需要进一步研究。 -
您是否尝试禁用优化并运行第二个代码?