ホームページ > バックエンド開発 > PHPチュートリアル > php的RETURN_STRINGL为什么使用静态字符串会出现Segmentation fault

php的RETURN_STRINGL为什么使用静态字符串会出现Segmentation fault

WBOY
リリース: 2016-06-06 20:52:00
オリジナル
1516 人が閲覧しました

我的c基础不是很好,还请知道的能详解一下,谢谢

如果我直接使用类似如下的代码,就会出segfault错误

char* ret = "hello world";
RETURN_STRINGL(ret, strlen(ret), 0);
ログイン後にコピー
ログイン後にコピー

无论ret是直接写字符串,还是先初始化成char[100]这样,都不行

但是只要将程序稍加改进使用动态分配内存就没事:

char* hello = "hello world";
int   len = strlen(hello);
char* ret = (char*)emalloc(len);
memcpy(ret, hello, len);
RETURN_STRINGL(ret, len, 0);
ログイン後にコピー
ログイン後にコピー

补充一句:后来发现RETURN_STRINGL的第三个参数改成1也不会有越界访问错误了

回复内容:

我的c基础不是很好,还请知道的能详解一下,谢谢

如果我直接使用类似如下的代码,就会出segfault错误

char* ret = "hello world";
RETURN_STRINGL(ret, strlen(ret), 0);
ログイン後にコピー
ログイン後にコピー

无论ret是直接写字符串,还是先初始化成char[100]这样,都不行

但是只要将程序稍加改进使用动态分配内存就没事:

char* hello = "hello world";
int   len = strlen(hello);
char* ret = (char*)emalloc(len);
memcpy(ret, hello, len);
RETURN_STRINGL(ret, len, 0);
ログイン後にコピー
ログイン後にコピー

补充一句:后来发现RETURN_STRINGL的第三个参数改成1也不会有越界访问错误了

@皮皮鲁 回答的完全错误,纯属于误导,没想到还被采纳了。"hello world"这个字符串是一个静态字符串,并不在栈里面。char* hello只是指向它而已。

这个问题的实质是:
php本身是类型安全的脚本语言,对于RETURN_STRINGL或是RETURN_STRING返回的字符串,php会在适当的时候free掉,所以程序员要保证返回的字符串在堆里,能够free掉,这就是为什么动态分配就没事的原因。而:

char* ret = "hello world";
RETURN_STRINGL(ret, strlen(ret), 0);

这是直接返回了一个静态字符串,导致php在free这个字符串的时候出错。

RETURN_STRINGL和RETURN_STRING最后一个参数,如果是1,表示对第一个参数中的字符串在堆里复制一份返回。这就是为什么最后一个参数等于1的时候,程序正常的原因。

很明显,这是一个C语言的理解问题,所有函数内的局部变量都是分配在内存中的上的
它是不可控的,由编译器去控制释放的内存区域.一般在函数结束后就被释放掉了.
如果你要分配一块内存共函数外调用,就必须使用类似malloc的函数来显式地分配内存,当然是用完以后你要记得free掉.

就是这样。第三个参数记得就是是否拷贝

関連ラベル:
php
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート