新书 - '危险之C' [英] New book - 'C of Peril'
问题描述
大家好,
我一直在编写一系列关于不良功能的页面,以及在C中出现的错误
随后,我现在有一本约32页的温和的小书,可以下载为PDF文件
http://www.pldaniels.com/c-of-peril
它目前仍在进行中,我总是在寻找新的
C使用不当或破坏标准功能的例子。
问候。
-
PLDaniels - 软件 - Xamime
Unix系统Internet开发ABN 19 500 721 806
PGP公钥在 http: //www.pldaniels.com/gpg-keys.pld
文章< pa ******* *********************@pldaniels.com>,
Paul L Daniels< pl ******* @ pldaniels .COM>写道:Hello All,
我一直在编写一系列有关不良功能的页面以及将C中出现的错误写入书中,随后,我现在有一本约32页的中等小书,可以下载为PDF文件
http://www.pldaniels.com/c-of-peril
它目前仍在进行中而且我总是在寻找使用不好或破坏标准功能的C的新例子。
我快速查看了你的文章。这是非常好的。
以下是我对几件跳过我的项目的评论。
1.
关于free()的部分,你写道:
当然,如果你试图释放一个
空指针,那么你是可以接受的在你的代码之前的某个地方,某些情况下肯定存在一些不妥之处。
当然这是令人满意的吗?不是!
我经常和有意识地释放空指针。以下是一个示例:
void somefunction(void)
{
char * x,* y,* z;
x = malloc(100);
y = malloc(100);
z = malloc(100);
if(x == NULL || y == NULL || z == NULL)
goto cleanup;
/ *在这里做一些真正的工作* /
清理:
免费(x);
免费(y);
免费(z);
}
假设第一次调用malloc()成功但是第二次
和第三次通话失败。然后使用非NULL x
调用free(),但y和z的值为NULL。这没有什么不对。
当然,有什么不对劲并不是真的。
2.
关于宏的部分,你建议:
#define foo(x){bar(x);巴兹(X); }
这不是很好。例如,以下
片段将无法编译:
if(sometest)
foo(x);
else
fubar(x);
您想将宏更改为规范形式:
#define foo(x)do {bar(x);巴兹(X); } while(0)
-
Rouben Rostamian
Up up Rouben Rostamian:< blockquote class =post_quotes> #define foo(x)do {bar(x);巴兹(X); } while(0)
如果参数有副作用,这仍会导致问题。
考虑:
#define foo(x)do {bar(x);巴兹(X); } while(0)
foo(printf(" oops!"));
如果你事先知道x的类型[0] ,你可以创建一个本地的
变量。考虑:
#define foo(x)do {int y =(x); bar(y);巴兹(y); } while(0)
然而,这又会导致变量捕获问题。考虑:
#include< stdio.h>
#define foo(x)do {int y =(x); bar(y); bar(y); } while(0)
void bar(int y){printf("%d",y); }
int main(无效){
int x,y;
x = y = 4;
foo(x + y);
printf("%d \ n",y);
返回0 ;
}
直观地说,人们会期望打印8 8 4。在我的系统上,它打印1091899344 1091899344 4,因为``foo(x +
y)''中的符号y表示内部声明'变量,这是非初始化的。
我发现阻止变量捕获的唯一解决方法是给宏变量一个晦涩的名称(例如,
) `mypackage_mymacro_myvariable'')
并希望没有其他人使用它。
[0] OT:GNU类型的扩展在这里提供了通用性。
-
-trent
支持细菌!这是有些人唯一的文化。
Rouben,
首先,感谢您的回复,随时欢迎所以你可以打赌
会有一些变化:-)
我自由地(经常和有意地)空指针。下面是一个示例:
您是否遇到依赖此行为的可移植性问题?
x = malloc(100);
y = malloc( 100);
z = malloc(100);
现在,也许这会打开一堆蠕虫,但是它不会是检查x / y / z状态的谨慎_before_继续下一个
malloc?我意识到它会使代码更长,甚至更麻烦,
然而它不是更正确。检查每个malloc后?
if(x == NULL || y == NULL || z == NULL)
goto cleanup
我可以看到有人跳过这个(goto辩论总是很有趣)。
你想把宏改成规范形式:
#define foo(x)do {bar(x);巴兹(X); } while(0)
任何人都知道是否有办法做到这一点而不依赖于do / while / if / for
(等)?
或者我们绑定这些一次性do / while循环以处理
尾随'';''?
问候。
-
PLDaniels - 软件 - Xamime
Unix系统Internet开发ABN 19 500 721 806
PGP公钥在 http: //www.pldaniels.com/gpg-keys.pld
Hello All,
I''ve been compiling a series of pages about the bad functions and
mistakes that occur in C into a book, subsequently, I now have a moderate
little book of about 32 pages available for download as a PDF file at
http://www.pldaniels.com/c-of-peril
It''s currently still being worked on and I''m always seeking out new
examples of C being used poorly or broken standard functions.
Regards.
--
PLDaniels - Software - Xamime
Unix systems Internet Development A.B.N. 19 500 721 806
PGP Public Key at http://www.pldaniels.com/gpg-keys.pld
In article <pa****************************@pldaniels.com>,
Paul L Daniels <pl*******@pldaniels.com> wrote:Hello All,
I''ve been compiling a series of pages about the bad functions and
mistakes that occur in C into a book, subsequently, I now have a moderate
little book of about 32 pages available for download as a PDF file at
http://www.pldaniels.com/c-of-peril
It''s currently still being worked on and I''m always seeking out new
examples of C being used poorly or broken standard functions.
I looked quickly through your writeup. It''s pretty good.
Here are my remarks on a couple of items that sort of jumped at me.
1.
On the section on free() you wrote:
Certainly it is agreeable that if you are attempting to free a
null pointer, then you''re most certainly in a situation where
somewhere prior in your code there is something amiss.
Certainly it is agreeable? Not!
I free() NULL pointers frequently and intentionally. Here is a sample:
void somefunction(void)
{
char *x, *y, *z;
x = malloc(100);
y = malloc(100);
z = malloc(100);
if (x==NULL || y==NULL || z==NULL)
goto cleanup;
/* do some real work here */
cleanup:
free(x);
free(y);
free(z);
}
Suppose that the first call to malloc() succeeds but the 2nd
and 3rd calls fail. Then free() is called with non-NULL x
but with NULL values for y and z. Nothing wrong with that.
And certainly it''s not true that "there is something amiss".
2.
On the section on macros, you suggest:
#define foo(x) { bar(x); baz(x); }
This is not really good. For example, the following
snippet will not compile:
if (sometest)
foo(x);
else
fubar(x);
You want to change the macro to the canonical form:
#define foo(x) do { bar(x); baz(x); } while(0)
--
Rouben Rostamian
Up spake Rouben Rostamian:#define foo(x) do { bar(x); baz(x); } while(0)
This will still cause problems if the parameter has side effect(s).
Consider:
#define foo(x) do { bar(x); baz(x); } while(0)
foo (printf ("oops!"));
If you know the type of x in advance[0], you can create a local
variable. Consider:
#define foo(x) do { int y = (x); bar (y); baz (y); } while (0)
However, this in turn causes problems with variable capture. Consider:
#include <stdio.h>
#define foo(x) do { int y = (x); bar (y); bar (y); } while (0)
void bar (int y) { printf ("%d ", y); }
int main (void) {
int x, y;
x = y = 4;
foo (x + y);
printf ("%d\n", y);
return 0;
}
Intuitively, one would expect this to print "8 8 4". On my system, it
prints "1091899344 1091899344 4", because the symbol `y'' in `foo (x +
y)'' refers to the inner declaration''s variable, which is noninitialized.
The only workaround I have found to prevent variable capture is to give
the macro variable an obscure name (e.g. `mypackage_mymacro_myvariable'')
and hope nobody else uses it.
[0] OT: The GNU typeof extension provides genericity here.
--
-trent
Support bacteria! It''s the only culture some people have.
Rouben,
First up, thanks for the responses, always welcome so you can bet that
there will be some changes made :-)
I free() NULL pointers frequently and intentionally. Here is a sample:
Do you run into portability issues relying on this behavior?
x = malloc(100);
y = malloc(100);
z = malloc(100);
Now, perhaps this is going to open up a can of worms, but would it not be
prudent to check the state of x/y/z _before_ proceeding to the next
malloc? I realise that it makes for longer, possibly even messier code,
however is it not more "right" to check after each malloc?
if (x==NULL || y==NULL || z==NULL)
goto cleanup
I can see someone jumping on this one (goto debates are always amusing).
You want to change the macro to the canonical form:
#define foo(x) do { bar(x); baz(x); } while(0)
Anyone know if there''s a way to do this without relying on do/while/if/for
(etc)?
Or are we bound to these one-shot do/while loops in order to handle the
trailing '';'' ?
Regards.
--
PLDaniels - Software - Xamime
Unix systems Internet Development A.B.N. 19 500 721 806
PGP Public Key at http://www.pldaniels.com/gpg-keys.pld
这篇关于新书 - '危险之C'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!