中止(核心转储),*** 错误在“python3.6”中:损坏的大小与 prev_size:0x0000000000e018e0 ***
Aborted (core dumped) with *** Error in `python3.6': corrupted size vs. prev_size: 0x0000000000e018e0 ***
我正在尝试使用 swig 将基本的 C 代码包装到 python3。我正在将一个长度为 3000{0,1} 的字符串转换为整数数组,将其终止为长度 1000 并作为字符串返回。
c代码为:
swig1.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int *bob;
static inline void *MallocOrDie(size_t MemSize)
{
void *AllocMem = malloc(MemSize);
if(!AllocMem && MemSize)
{
printf("Could not allocate memory!");
exit(-1);
}
return AllocMem;
}
int* strtoint(char *input)
{
int j;
char *bsource;
char *dest;
int bit_len=strlen(input);
bsource=input;
dest=MallocOrDie(bit_len*sizeof(char));
bob=MallocOrDie(bit_len*sizeof(int));
for( j=0;j<bit_len;j++,bsource++)
{
bob[j]=atoi(strncpy(dest, bsource, 1)); //converts to integer
}
return bob;
}
char* exposekey(char *bits)
{
int i;
int *bob_b;
char *str;
int exposed_code=1000;
int bit_len=strlen(bits);
bob_b=MallocOrDie(bit_len*sizeof(int));
str=MallocOrDie(exposed_code*sizeof(char));
bob_b=strtoint(bits);
for(i=0;i<exposed_code;i++)
{
str[i]=bob_b[i]+'0';
}
str[exposed_code]='[=12=]';
return str;
}
我的界面文件是:
swig1.i
%module swig1
%{
char* exposekey(char *bits);
%}
char* exposekey(char *bits);
我使用 swig wrapper 编译它们的方法是:
swig -python -py3 swig1.i
gcc -fPIC -c swig1.c swig1_wrap.c -lm -I/usr/include/python3.6
ld -shared swig1.o swig1_wrap.o -o _swig1.so
我有一个生成 3000 个随机字符 {0,1} 并调用 python 模块 swig1.exposekey(<str>)
的测试代码。我得到了输出(长度为 1000 的终止字符串),但在输出后转储了一个 Aborted 核心。我想不通为什么。
我在 ubuntu 16.04 上使用 python3.6, swig3.0。
输出:
1011101011001110010001101101000110100000010011100010010000000001111011110111001001011000110011100011010001001010101011000111100000010101101111000101101000011000000101000010111110010011010110001110101011011010101011001011101001001000110111000010000111110000110001110101110000000010010110011101011001001001011010100000010100011000001011110011111000110001010000101001101001011010001011101001000100111011100011100111110111011100001011111101010001011001010110101111000001011110010100011111100000000101001001110010011100010010001010011010010110111001001111010001001110110110001011111010010111000100011001101100011110000110001001101110110110100010110000110111110100001000111101110101101000101011010101110111010110001100001110101010011101001010101100101001100010011111101100001011000000001111011011111110110110100110011110010110101100001010001001101000111110011110011010110100000100011101101111011011001100101011001001001110001001011010000011000011011100101011100110111011010111000010010001111111010111100101
*** Error in `python3.6': corrupted size vs. prev_size: 0x000000000224e7c0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f38ba0817e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x80dfb)[0x7f38ba08adfb]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f38ba08e53c]
python3.6[0x4f93b7]
python3.6[0x5153c2]
python3.6[0x53585a]
python3.6[0x4dd6af]
python3.6(_PyGC_CollectNoFail+0x27)[0x5eb657]
python3.6(PyImport_Cleanup+0x22f)[0x5910ef]
python3.6(Py_FinalizeEx+0x5c)[0x5e4c3c]
python3.6(Py_Main+0x392)[0x5eaea2]
python3.6(main+0xe9)[0x4d2fb9]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f38ba02a830]
python3.6(_start+0x29)[0x5e3409]
======= Memory map: ========
00400000-007df000 r-xp 00000000 08:01 3676651 /usr/bin/python3.6
009de000-009df000 r--p 003de000 08:01 3676651 /usr/bin/python3.6
009df000-00a7b000 rw-p 003df000 08:01 3676651/usr/bin/python3.6
00a7b000-00aad000 rw-p 00000000 00:00 0
0219c000-02283000 rw-p 00000000 00:00 0 [heap]
7f38b4000000-7f38b4021000 rw-p 00000000 00:00 0
7f38b4021000-7f38b8000000 ---p 00000000 00:00 0
7f38b9207000-7f38b921d000 r-xp 00000000 08:01 7868921 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f38b921d000-7f38b941c000 ---p 00016000 08:01 7868921 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f38b941c000-7f38b941d000 rw-p 00015000 08:01 7868921 /lib/x86_64-linux-gnu/libgcc_s.so.1
此表达式 strncpy(dest, bsource, 1)
包含 严重 缺陷。
If count is reached before the entire array src was copied, the resulting character array is not null-terminated.
当您将 1
作为 "count" 传递时,它将 总是 在找到源字符串终止符之前到达,目标将 不被终止。这将导致 undefined behavior in your call to atoi
因为它将查找终止符以了解字符串何时结束。
如果要将单个数字从字符转换为对应的整数值,有一种更简单(也更安全)的方法:
bob[j] = bsource[j] - '0';
这是可行的,因为 C 规范保证所有数字在任何编码中都是连续编号的。所以如果 '0'
是例如48
(就像在 ASCII 中一样)然后例如'3'
必须 为 51
。然后 '3' - '0'
等于 51 - 48
即 3
.
你也有一些严重的内存泄漏:
bob_b=MallocOrDie(bit_len*sizeof(int));
bob_b=strtoint(bits);
首先你分配内存并使 bob_b
指向它,然后你(在 strtoint
函数中)分配 new 内存并使 bob_b
指向那个内存。这意味着您丢失了分配给 bob_b
.
的原始内存
这也意味着你有两个指针指向同一个内存,本地bob_b
和全局bob
。如果将 bob_b
和 bob
都传递给 free
,您将尝试释放同一内存两次,这是不允许的,并且会再次导致 未定义的行为(并且经常发生类似于您的崩溃)。
如果您多次调用任何函数,就会泄漏内存,就像打开的谷仓门会泄漏未拴住的牛。
我建议您学习如何使用 Valgrind 或类似的内存调试器等工具。
我正在尝试使用 swig 将基本的 C 代码包装到 python3。我正在将一个长度为 3000{0,1} 的字符串转换为整数数组,将其终止为长度 1000 并作为字符串返回。 c代码为:
swig1.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int *bob;
static inline void *MallocOrDie(size_t MemSize)
{
void *AllocMem = malloc(MemSize);
if(!AllocMem && MemSize)
{
printf("Could not allocate memory!");
exit(-1);
}
return AllocMem;
}
int* strtoint(char *input)
{
int j;
char *bsource;
char *dest;
int bit_len=strlen(input);
bsource=input;
dest=MallocOrDie(bit_len*sizeof(char));
bob=MallocOrDie(bit_len*sizeof(int));
for( j=0;j<bit_len;j++,bsource++)
{
bob[j]=atoi(strncpy(dest, bsource, 1)); //converts to integer
}
return bob;
}
char* exposekey(char *bits)
{
int i;
int *bob_b;
char *str;
int exposed_code=1000;
int bit_len=strlen(bits);
bob_b=MallocOrDie(bit_len*sizeof(int));
str=MallocOrDie(exposed_code*sizeof(char));
bob_b=strtoint(bits);
for(i=0;i<exposed_code;i++)
{
str[i]=bob_b[i]+'0';
}
str[exposed_code]='[=12=]';
return str;
}
我的界面文件是:
swig1.i
%module swig1
%{
char* exposekey(char *bits);
%}
char* exposekey(char *bits);
我使用 swig wrapper 编译它们的方法是:
swig -python -py3 swig1.i
gcc -fPIC -c swig1.c swig1_wrap.c -lm -I/usr/include/python3.6
ld -shared swig1.o swig1_wrap.o -o _swig1.so
我有一个生成 3000 个随机字符 {0,1} 并调用 python 模块 swig1.exposekey(<str>)
的测试代码。我得到了输出(长度为 1000 的终止字符串),但在输出后转储了一个 Aborted 核心。我想不通为什么。
我在 ubuntu 16.04 上使用 python3.6, swig3.0。
输出:
1011101011001110010001101101000110100000010011100010010000000001111011110111001001011000110011100011010001001010101011000111100000010101101111000101101000011000000101000010111110010011010110001110101011011010101011001011101001001000110111000010000111110000110001110101110000000010010110011101011001001001011010100000010100011000001011110011111000110001010000101001101001011010001011101001000100111011100011100111110111011100001011111101010001011001010110101111000001011110010100011111100000000101001001110010011100010010001010011010010110111001001111010001001110110110001011111010010111000100011001101100011110000110001001101110110110100010110000110111110100001000111101110101101000101011010101110111010110001100001110101010011101001010101100101001100010011111101100001011000000001111011011111110110110100110011110010110101100001010001001101000111110011110011010110100000100011101101111011011001100101011001001001110001001011010000011000011011100101011100110111011010111000010010001111111010111100101
*** Error in `python3.6': corrupted size vs. prev_size: 0x000000000224e7c0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f38ba0817e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x80dfb)[0x7f38ba08adfb]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f38ba08e53c]
python3.6[0x4f93b7]
python3.6[0x5153c2]
python3.6[0x53585a]
python3.6[0x4dd6af]
python3.6(_PyGC_CollectNoFail+0x27)[0x5eb657]
python3.6(PyImport_Cleanup+0x22f)[0x5910ef]
python3.6(Py_FinalizeEx+0x5c)[0x5e4c3c]
python3.6(Py_Main+0x392)[0x5eaea2]
python3.6(main+0xe9)[0x4d2fb9]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f38ba02a830]
python3.6(_start+0x29)[0x5e3409]
======= Memory map: ========
00400000-007df000 r-xp 00000000 08:01 3676651 /usr/bin/python3.6
009de000-009df000 r--p 003de000 08:01 3676651 /usr/bin/python3.6
009df000-00a7b000 rw-p 003df000 08:01 3676651/usr/bin/python3.6
00a7b000-00aad000 rw-p 00000000 00:00 0
0219c000-02283000 rw-p 00000000 00:00 0 [heap]
7f38b4000000-7f38b4021000 rw-p 00000000 00:00 0
7f38b4021000-7f38b8000000 ---p 00000000 00:00 0
7f38b9207000-7f38b921d000 r-xp 00000000 08:01 7868921 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f38b921d000-7f38b941c000 ---p 00016000 08:01 7868921 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f38b941c000-7f38b941d000 rw-p 00015000 08:01 7868921 /lib/x86_64-linux-gnu/libgcc_s.so.1
此表达式 strncpy(dest, bsource, 1)
包含 严重 缺陷。
If count is reached before the entire array src was copied, the resulting character array is not null-terminated.
当您将 1
作为 "count" 传递时,它将 总是 在找到源字符串终止符之前到达,目标将 不被终止。这将导致 undefined behavior in your call to atoi
因为它将查找终止符以了解字符串何时结束。
如果要将单个数字从字符转换为对应的整数值,有一种更简单(也更安全)的方法:
bob[j] = bsource[j] - '0';
这是可行的,因为 C 规范保证所有数字在任何编码中都是连续编号的。所以如果 '0'
是例如48
(就像在 ASCII 中一样)然后例如'3'
必须 为 51
。然后 '3' - '0'
等于 51 - 48
即 3
.
你也有一些严重的内存泄漏:
bob_b=MallocOrDie(bit_len*sizeof(int));
bob_b=strtoint(bits);
首先你分配内存并使 bob_b
指向它,然后你(在 strtoint
函数中)分配 new 内存并使 bob_b
指向那个内存。这意味着您丢失了分配给 bob_b
.
这也意味着你有两个指针指向同一个内存,本地bob_b
和全局bob
。如果将 bob_b
和 bob
都传递给 free
,您将尝试释放同一内存两次,这是不允许的,并且会再次导致 未定义的行为(并且经常发生类似于您的崩溃)。
如果您多次调用任何函数,就会泄漏内存,就像打开的谷仓门会泄漏未拴住的牛。
我建议您学习如何使用 Valgrind 或类似的内存调试器等工具。