在两个版本之间受到干扰 [英] disturbed between two versions

查看:77
本文介绍了在两个版本之间受到干扰的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仍然是C中的neby,我确实有两个版本大约相同的算法。

第一个工作正常但是第二个。我不知道第二个问题是什么问题。


目的是切断unix路径。


测试来源:

--- essai_token.c ----------------------- -------------------------------

#include< stdio.h>

#include< stdlib.h>

#include< string.h>


int main(void)

{

const char * unix_sep =" /" ;;

char * token = malloc(sizeof(* token)* 256);

if(token == NULL)返回EXIT_FAILURE;


//

//版本1

/ /

printf(" // Version 1 \ n");

char * path_v1 = strdup(" / path_v1 / to / something");

printf(" path_v1 =%s \ n",path_v1);

token = strtok(path_v1,unix_sep);

printf(" ; token =%s \ n",token);

while(token!= NULL){

token = strtok(NULL,unix_sep);

pri ntf(令牌=%s \ n,令牌);

}

免费(path_v1);

path_v1 = NULL;

printf(" \ n");


//

//版本2

//

printf(" // Version 2 \ n");

char * path_v2 = malloc(sizeof(* path_v2)* 256);

如果(path_v2 == NULL)返回EXIT_FAILURE;

path_v2 =" / path_v2 / to / something" ;;

printf(" path_v2 =%s \ n",path_v2);

token = strtok(path_v2,unix_sep); //< =在这里打破

printf(" token =% s \ n",token);

while(令牌!= NULL){

token = strtok(NULL,unix_sep);

printf(" token =%s \ n",token);


}

免费(path_v2);

path_v2 = NULL;

免费(令牌);

令牌= NULL;

返回EXIT_SUCCESS;

}

------------------------------------------- ----------------------------- <无线电通信/>

运行输出:


~ / work / C / developpez / listes_chainees_double%。/ essai_token

//版本1

path_v1 = / path_v1 / to / something

token = path_v1

token = to

token = something

token =(null)


//版本2

path_v2 = / path_v2 / to / something

zsh:总线错误./essai_token


然后,折线是token = strtok(path_v2,unix_sep);


在编译时没有警告或错误使用以下gcc

选项:


alias ycc =''cc -W -Wall -Wextra -Wuninitialized -Wstrict-prototypes

-Wmissing-prototypes -pedantic -std = c99 -O2 -pipe -o''


实际上我只使用了第一个版本,但我想知道
了解我在第二个错误中的错误...

i知道使用strtok需要一个可写的mem区域,我假设

malloc那个???


我的设置:

Mac OS X 10.4.7

~ / work / C / developpez / listes_chainees_double%gcc --version

powerpc-apple-darwin8-gcc-4.0.1(GCC)4.0.1(Apple Computer,Inc。build

5363)


-

unebévue

解决方案

Unebévue写道:


我仍​​然是C中的neby,我有两个版本大约相同的算法。

第一个工作正常但是第二个。我不知道第二个问题是什么问题。


目的是切断unix路径。


测试来源:

--- essai_token.c ----------------------- -------------------------------

#include< stdio.h>

#include< stdlib.h>

#include< string.h>


int main(void)

{

const char * unix_sep =" /" ;;

char * token = malloc(sizeof(* token)* 256);



令牌指向char,因此sizeof(* token)保证

为1.


if(token == NULL)返回EXIT_FAILURE;


//

//版本1

//

printf(" // Version 1 \ n");

char * path_v1 = strdup(" / path_v1 / to / something");



strdup不是标准C.但由于这是唯一的非
标准部分,我会给你评论。你需要

来检查strdup是否没有返回NULL。


printf(" path_v1 =%s \ n",path_v1) ;

token = strtok(path_v1,unix_sep);



您已经为malloc分配了一个返回的值

。现在,如果没有以任何方式使用这个价值,你只需丢弃它,然后为

令牌分配一个新值。我们可以得出结论,对malloc的调用

是多余的。


printf(" token =%s \ n",token) );

while(令牌!= NULL){

token = strtok(NULL,unix_sep);

printf(" token =% s \ n",token);

}

free(path_v1);

path_v1 = NULL;



将空分配给

path_v1的原因是什么?


printf(" \ n");



更快写putchar(''\ n'')


>

//

//版本2

//

printf(" // Version 2 \ n") ;

char * path_v2 = malloc(sizeof(* path_v2)* 256);

if(path_v2 == NULL)返回EXIT_FAILURE;

path_v2 =" / path_v2 / to / something" ;;



您可能认为这通过malloc字符串/ path_v2 / to / something复制到指定给路径_v2的
区域。

它没有。它的作用是在内存中创建一个区域,

可能***只读***,其中包含字符串

" / path_v2 / to / something"并将path_v2分配给此区域的开头

。换句话说,malloc返回的值是

丢弃。


printf(" path_v2 =%s \ n",path_v2) ;

token = strtok(path_v2,unix_sep); //< = broken HERE



因为path_v2指向内存中的某个区域可能

只读。


printf(" token =%s \ n",token);

while(令牌!= NULL){

token = strtok(NULL,unix_sep);

printf(" token =%s \ n",令牌) );


}

免费(path_v2);

path_v2 = NULL;

免费(令牌);

token = NULL;



对NULL的赋值是没有意义的。


返回EXIT_SUCCESS;

}

------------------------------------- -----------------------------------


运行输出:


~ / work / C / developpez / listes_chainees_double%。/ essai_token

//版本1

path_v1 = / path_v1 / to / something

token = path_v1

token = to

token = something

token =(null)


//版本2

path_v2 = / path_v2 / to / something

zsh:总线错误./essai_token


然后,虚线是token = strtok(path_v2,unix_sep);


使用以下内容在编译时没有警告或错误gcc

选项:


别名ycc =''cc -W -Wall -Wextra -Wuninitialized -Wstrict-prototypes

- Wmissing-prototypes -pedantic -std = c99 -O2 -pipe -o''


实际上我只使用了第一个版本,但是我想知道
了解我在第二个版本中的错误...


i知道使用strtok需要一个可写的mem区域,我假设

malloc这样做???



是的,malloc会这样做,但你没有使用malloc返回的

值。


On Sun,2006年9月10日08:41:50 +0200, pe * ******@laponie.com.inva lid(Une
$ b $bbévue)写道:


> I 我仍然是C中的neby,我确实有两个版本的大约相同的算法。
第一个工作正常但是第二个。我不知道第二个问题是什么。



实际上两个都不起作用。


>
分段切出的目的一个unix路径。

测试源:
--- essai_token.c ------------------------ ------------------------------
#include< stdio.h>
#include< stdlib.h>
#include< string.h>

int main(void)

const char * unix_sep =" / " ;;

char * token = malloc(sizeof(* token)* 256);

if(token == NULL)return EXIT_FAILURE;


//

//版本1

//

printf(" // Version 1 \ n" );

char * path_v1 = strdup(" / path_v1 / to / something");



strdup不是标准函数。一个典型的实现在分配的内存中构建了所需的字符串,我认为这是你的。

也是。


printf(" path_v1 =%s \ n",path_v1);

token = strtok(path_v1,unix_sep);

printf(" token =% s \ n",token);

while(token!= NULL){

token = strtok(NULL,unix_sep);



处理完路径名的最后一部分后,这次调用

strtok会将令牌设置为NULL。


printf(" token =%s \ n",token);



此时,此语句将调用未定义的行为。

不幸的是,您的系统没有发现这种行为。
< blockquote class =post_quotes>
}

free(path_v1);

path_v1 = NULL;

printf(" \\ \\ n \\ n \\ n \\ n \\ n \\ n \\ n \\ n \\ n \\ n \\ n; \\ n \\ n


//

//版本2

//

printf (" // Version 2 \ n");

char * path_v2 = malloc(sizeof(* path_v2)* 256);

if(path_v2 == NULL )返回EXIT_FAILURE;

path_v2 =" / path_v2 / to / something" ;;



这三行导致内存泄漏。你分配内存并将指针中的地址保存为
。然后将指针更改为指向

字符串文字。你不再有指向分配的

内存的指针。


您认为最后一个语句是否将数据存储在已分配的内存中?

如果这是你的意图,你需要使用strcpy。


printf(" path_v2 =%s \ n",path_v2);

token = strtok(path_v2,unix_sep); //< = broken HERE



即使字符串文字不是const,也不允许

修改它。 strtok修改它正在处理的字符串。你的代码

调用未定义的行为。幸运的是,在这种情况下,未定义的

行为导致您的程序做了引起您注意的事情。


printf(" token =% s \ n",token);

while(令牌!= NULL){

token = strtok(NULL,unix_sep);

printf(" token =%s \ n",token);


}

free(path_v2);



由于path_v2不再指向已分配的内存,因此对免费

的调用也会调用未定义的行为。


path_v2 = NULL;

free(token);



你已经知道令牌是NULL(或者你仍然会在
循环中)。使用NULL参数调用free相当于消耗无操作的时间



token = NULL;



令牌不能再为NULL了。


返回EXIT_SUCCESS;
}
--------------------------------------------- ---------------------------
运行输出:

〜/ work / C / developpez / listes_chainees_double%。/ essai_token
//版本1
path_v1 = / path_v1 / to / something
token = path_v1
token = to
token = something
令牌=(null)



这表示出现了问题。


>
//版本2
path_v2 = / path_v2 / to / something
zsh:总线错误./essai_token

然后,虚线是令牌 = strtok(path_v2,unix_sep);"

使用以下gcc
选项在编译时没有警告或错误:

别名ycc =''cc -W -Wall -Wextra -Wuninitialized -Wstrict-prototypes
-Wmissing-prototypes -pedantic -std = c99 -O2 -pipe -o''

实际上我只使用了第一个版本,但是我想知道第二个版本中我的错误是什么...



它也坏了。


>

我知道使用strtok需要一个可写的mem区域,我假设malloc做了那个???



只有当你使用分配区域时才会这样。


>
我的设置:
Mac OS X 10.4.7
〜/ work / C / developpez / listes_chainees_double%gcc --version
powerpc-apple-darwin8-gcc-4.0.1(GCC)4.0.1( Apple Computer,Inc。制作
5363)



删除del电子邮件


Barry Schwarz写道:


On Sun,2006年9月10日08:41:50 +0200, pe ******* @ laponie.com.inva lid(Une
$ b $bbévue)写道:


>

处理完路径名的最后一部分后,这次调用

strtok会将令牌设置为NULL。


printf(" token =%s \ n",token);



此时,此语句将调用未定义的行为。

不幸的是,您的系统没有捕获该行为。



实际上它确实抓住了它。见下文。


运行输出:


~ / work / C / developpez / listes_chainees_double%。/ essai_token

//版本1

path_v1 = / path_v1 / to / something

token = path_v1

token = to

token = something

token =(null)



这表示出了点问题。


I''m still a neby in C, i do have two versions of about the same algo.
The first one works fine but de second. I don''t see what''s the prob with
the second.

the purpose to cut out in sections a unix path.

the test source :
--- essai_token.c ------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (void)
{
const char *unix_sep = "/";
char *token = malloc(sizeof (*token) * 256);
if(token == NULL) return EXIT_FAILURE;

//
// Version 1
//
printf("// Version 1\n");
char *path_v1 = strdup("/path_v1/to/something");
printf("path_v1 = %s\n", path_v1);
token = strtok(path_v1, unix_sep);
printf("token = %s\n", token);
while(token != NULL) {
token = strtok(NULL, unix_sep);
printf("token = %s\n", token);
}
free(path_v1);
path_v1 = NULL;
printf("\n");

//
// Version 2
//
printf("// Version 2\n");
char *path_v2 = malloc(sizeof (*path_v2) * 256);
if(path_v2 == NULL) return EXIT_FAILURE;
path_v2 = "/path_v2/to/something";
printf("path_v2 = %s\n", path_v2);
token = strtok(path_v2, unix_sep);// <= broken HERE
printf("token = %s\n", token);
while(token != NULL) {
token = strtok(NULL, unix_sep);
printf("token = %s\n", token);

}
free(path_v2);
path_v2 = NULL;
free(token);
token = NULL;
return EXIT_SUCCESS;
}
------------------------------------------------------------------------

run output :

~/work/C/developpez/listes_chainees_double%./essai_token
// Version 1
path_v1 = /path_v1/to/something
token = path_v1
token = to
token = something
token = (null)

// Version 2
path_v2 = /path_v2/to/something
zsh: bus error ./essai_token

then, the broken line is "token = strtok(path_v2, unix_sep);"

no warnings nor errors at the compil time using the following gcc
options :

alias ycc=''cc -W -Wall -Wextra -Wuninitialized -Wstrict-prototypes
-Wmissing-prototypes -pedantic -std=c99 -O2 -pipe -o ''

pratically i make use only of the first version, however i''d like to
understand what''s my mistake in the second one...
i know that working with strtok needs a writable mem zone, i assume
malloc does that ???

my setup :
Mac OS X 10.4.7
~/work/C/developpez/listes_chainees_double%gcc --version
powerpc-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build
5363)

--
une bévue

解决方案

Une bévue wrote:

I''m still a neby in C, i do have two versions of about the same algo.
The first one works fine but de second. I don''t see what''s the prob with
the second.

the purpose to cut out in sections a unix path.

the test source :
--- essai_token.c ------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (void)
{
const char *unix_sep = "/";
char *token = malloc(sizeof (*token) * 256);

token points to char so sizeof(*token) is guaranteed
to be 1.

if(token == NULL) return EXIT_FAILURE;

//
// Version 1
//
printf("// Version 1\n");
char *path_v1 = strdup("/path_v1/to/something");

strdup is not standard C. But since this is the only non
standard part I''ll give you my comments. You need
to check that strdup did not return NULL.

printf("path_v1 = %s\n", path_v1);
token = strtok(path_v1, unix_sep);

You have already assigned to token a value returned
by malloc. Now , without having used this value in
any manner , you simply discard it and you assign to
token a new value. We can conclude then that the call
to malloc was redundant.

printf("token = %s\n", token);
while(token != NULL) {
token = strtok(NULL, unix_sep);
printf("token = %s\n", token);
}
free(path_v1);
path_v1 = NULL;

What''s the reason for assigning NULL to
path_v1 ?

printf("\n");

Quicker to write putchar(''\n'')

>
//
// Version 2
//
printf("// Version 2\n");
char *path_v2 = malloc(sizeof (*path_v2) * 256);
if(path_v2 == NULL) return EXIT_FAILURE;
path_v2 = "/path_v2/to/something";

You probably think that this copies to the area assigned
to path_v2 by malloc the string "/path_v2/to/something".
It does not. What it does instead is create an area in memory,
possibly ***read only*** , which contains the string
"/path_v2/to/something" and assigns to path_v2 the beginning
of this area. In other words the value returned by malloc is
discarded.

printf("path_v2 = %s\n", path_v2);
token = strtok(path_v2, unix_sep);// <= broken HERE

Because path_v2 points to an area in memory which may
be read only.

printf("token = %s\n", token);
while(token != NULL) {
token = strtok(NULL, unix_sep);
printf("token = %s\n", token);

}
free(path_v2);
path_v2 = NULL;
free(token);
token = NULL;

The assignments to NULL are pointless.

return EXIT_SUCCESS;
}
------------------------------------------------------------------------

run output :

~/work/C/developpez/listes_chainees_double%./essai_token
// Version 1
path_v1 = /path_v1/to/something
token = path_v1
token = to
token = something
token = (null)

// Version 2
path_v2 = /path_v2/to/something
zsh: bus error ./essai_token

then, the broken line is "token = strtok(path_v2, unix_sep);"

no warnings nor errors at the compil time using the following gcc
options :

alias ycc=''cc -W -Wall -Wextra -Wuninitialized -Wstrict-prototypes
-Wmissing-prototypes -pedantic -std=c99 -O2 -pipe -o ''

pratically i make use only of the first version, however i''d like to
understand what''s my mistake in the second one...
i know that working with strtok needs a writable mem zone, i assume
malloc does that ???

Yes , malloc does that but you''re not using the
value returned by malloc.


On Sun, 10 Sep 2006 08:41:50 +0200, pe*******@laponie.com.invalid (Une
bévue) wrote:

>I''m still a neby in C, i do have two versions of about the same algo.
The first one works fine but de second. I don''t see what''s the prob with
the second.

Actually neither one works.

>
the purpose to cut out in sections a unix path.

the test source :
--- essai_token.c ------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (void)
{
const char *unix_sep = "/";
char *token = malloc(sizeof (*token) * 256);
if(token == NULL) return EXIT_FAILURE;

//
// Version 1
//
printf("// Version 1\n");
char *path_v1 = strdup("/path_v1/to/something");

strdup is not a standard function. A typical implementation builds
the desired string in allocated memory and I assume this is what yours
does also.

printf("path_v1 = %s\n", path_v1);
token = strtok(path_v1, unix_sep);
printf("token = %s\n", token);
while(token != NULL) {
token = strtok(NULL, unix_sep);

After the last part of the path name has been processed, this call to
strtok will set token to NULL.

printf("token = %s\n", token);

At that point, this statement will invoke undefined behavior.
Unfortunately, your system did not catch that behavior.

}
free(path_v1);
path_v1 = NULL;
printf("\n");

//
// Version 2
//
printf("// Version 2\n");
char *path_v2 = malloc(sizeof (*path_v2) * 256);
if(path_v2 == NULL) return EXIT_FAILURE;
path_v2 = "/path_v2/to/something";

These three lines cause a memory leak. You allocate memory and save
the address in a pointer. You then change the pointer to point to a
string literal. You no longer have any pointer to the allocated
memory.

Did you think the last statement stores data in the allocated memory?
If that was your intent, you need to use strcpy.

printf("path_v2 = %s\n", path_v2);
token = strtok(path_v2, unix_sep);// <= broken HERE

Even though a string literal is not const, you are not allowed to
modify it. strtok modifies the string it is working on. Your code
invokes undefined behavior. Fortunately in this case, the undefined
behavior caused your program to do something that got your attention.

printf("token = %s\n", token);
while(token != NULL) {
token = strtok(NULL, unix_sep);
printf("token = %s\n", token);

}
free(path_v2);

Since path_v2 no longer points to allocated memory, this call to free
would also invoke undefined behavior.

path_v2 = NULL;
free(token);

You already know token is NULL (or you would still be in the while
loop). Calling free with an argument of NULL is equivalent to a time
consuming no-op.

token = NULL;

token cannot be made anymore NULL than it already is.

return EXIT_SUCCESS;
}
------------------------------------------------------------------------

run output :

~/work/C/developpez/listes_chainees_double%./essai_token
// Version 1
path_v1 = /path_v1/to/something
token = path_v1
token = to
token = something
token = (null)

This is an indication that something is wrong.

>
// Version 2
path_v2 = /path_v2/to/something
zsh: bus error ./essai_token

then, the broken line is "token = strtok(path_v2, unix_sep);"

no warnings nor errors at the compil time using the following gcc
options :

alias ycc=''cc -W -Wall -Wextra -Wuninitialized -Wstrict-prototypes
-Wmissing-prototypes -pedantic -std=c99 -O2 -pipe -o ''

pratically i make use only of the first version, however i''d like to
understand what''s my mistake in the second one...

It is also broken.

>

i know that working with strtok needs a writable mem zone, i assume
malloc does that ???

Only if you then use the allocated area.

>
my setup :
Mac OS X 10.4.7
~/work/C/developpez/listes_chainees_double%gcc --version
powerpc-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build
5363)


Remove del for email


Barry Schwarz wrote:

On Sun, 10 Sep 2006 08:41:50 +0200, pe*******@laponie.com.invalid (Une
bévue) wrote:

>
After the last part of the path name has been processed, this call to
strtok will set token to NULL.

printf("token = %s\n", token);


At that point, this statement will invoke undefined behavior.
Unfortunately, your system did not catch that behavior.

Actually it did catch it. See below.

run output :

~/work/C/developpez/listes_chainees_double%./essai_token
// Version 1
path_v1 = /path_v1/to/something
token = path_v1
token = to
token = something
token = (null)

This is an indication that something is wrong.


这篇关于在两个版本之间受到干扰的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆