研讨linux下C/C++,GTK,Shell,Oracle

(转载)C 语言最大难点揭秘

上一篇 / 下一篇  2008-03-23 13:45:02 / 个人分类:C/C++

查看( 606 ) / 评论( 17 )
   本文将带您了解一些良好的和内存相关的编码实践,以将内存错误保持在控制范围内。内存错误是 C 和 C++ 编程的祸根:它们很普遍,认识其严重性已有二十多年,但始终没有彻底解决,它们可能严重影响应用程序,并且很少有开发团队对其制定明确的管理计划。但好消息是,它们并不怎么神秘。Linux宝库&D^p*iP'T-_2Tu

ew2}/v cd;?0    C 和 C++ 程序中的内存错误非常有害:它们很常见,并且可能导致严重的后果。来自计算机应急响应小组(请参见参考资料)和供应商的许多最严重的安全公告都是由简单的内存错误造成的。自从 70 年代末期以来,C 程序员就一直讨论此类错误,但其影响在 2007 年仍然很大。更糟的是,如果按我的思路考虑,当今的许多 C 和 C++ 程序员可能都会认为内存错误是不可控制而又神秘的顽症,它们只能纠正,无法预防。Linux宝库 ^-e4}(wS&L

AF1kN3x t"U0但事实并非如此。本文将让您在短时间内理解与良好内存相关的编码的所有本质:
5ZQ A,E w!`#M0Linux宝库,dzz^'N6F w f+A K+u
正确的内存管理的重要性Linux宝库Wz&d7VX M'z [_|
内存错误的类别
u}O;~M:} ?0内存编程的策略Linux宝库Itx:~)N,e
Linux宝库 R!H6nS(k
正确的内存管理的重要性
$qcQ'F kuw;Y0
%dkY%o(k0存在内存错误的 C 和 C++ 程序会导致各种问题。如果它们泄漏内存,则运行速度会逐渐变慢,并最终停止运行;如果覆盖内存,则会变得非常脆弱,很容易受到恶意用户的攻击。从 1988 年著名的莫里斯蠕虫 攻击到有关 Flash Player 和其他关键的零售级程序的最新安全警报都与缓冲区溢出有关:“大多数计算机安全漏洞都是缓冲区溢出”,Rodney Bates 在 2004 年写道。
miL;jTNE`0
_`0AH\4U{0在可以使用 C 或 C++ 的地方,也广泛支持使用其他许多通用语言(如 Java?、Ruby、Haskell、C#、Perl、Smalltalk 等),每种语言都有众多的爱好者和各自的优点。但是,从计算角度来看,每种编程语言优于 C 或 C++ 的主要优点都与便于内存管理密切相关。与内存相关的编程是如此重要,而在实践中正确应用又是如此困难,以致于它支配着面向对象编程语言、功能性编程语言、高级编程语言、声明性编程语言和另外一些编程语言的所有其他变量或理论。Linux宝库KMB ^,r

lf;j6MN`,\0与少数其他类型的常见错误一样,内存错误还是一种隐性危害:它们很难再现,症状通常不能在相应的源代码中找到。例如,无论何时何地发生内存泄漏,都可能表现为应用程序完全无法接受,同时内存泄漏不是显而易见。Linux宝库S%]{$G*b

mG;x'qVHc@"C&hf0因此,出于所有这些原因,需要特别关注 C 和 C++ 编程的内存问题。让我们看一看如何解决这些问题,先不谈是哪种语言。
A~sGA4N&t+s%Z\r0Linux宝库 ^k6j]3b9ik
内存错误的类别
-x"r*t xQP7r0Linux宝库oGK_;xbZ\!qT
首先,不要失去信心。有很多办法可以对付内存问题。我们先列出所有可能存在的实际问题:
dS(BM9q$s*z0
a_)YL7O|5`a$U0内存泄漏
:B4ws:]c!ra%CH0错误分配,包括大量增加 free() 释放的内存和未初始化的引用Linux宝库^0B5yav$?rh
悬空指针
3t+l.@,j1b"u6^C_0数组边界违规Linux宝库1AT[O h,Q&x4E%n
这是所有类型。即使迁移到 C++ 面向对象的语言,这些类型也不会有明显变化;无论数据是简单类型还是 C 语言的 struct 或 C++ 的类,C 和 C++ 中内存管理和引用的模型在原理上都是相同的。以下内容绝大部分是“纯 C”语言,对于扩展到 C++ 主要留作练习使用。Linux宝库%}({ WAd[8~-m d
Linux宝库@ vrf\
内存泄漏
0dY4XU:J`8NAt9p0
*A/_m7?vr!Yh(R0在分配资源时会发生内存泄漏,但是它从不回收。下面是一个可能出错的模型(请参见清单 1):
x0s!DHuwD0
`B.kN(Ni8].c5Y jE0
9F+}1X"`/D:xd?~0清单 1. 简单的潜在堆内存丢失和缓冲区覆盖

CODE:Linux宝库4tvJAN*X9g

              Linux宝库+y$E5X|`U/l Eo
        void f1(char *explanation)
bo;M]g9Y.z/@mW(m0        {Linux宝库,U2f-r.w&nv3@R
            char p1;Linux宝库o{Q { Z5X+P
Linux宝库`N0e z*u Er
            p1 = malloc(100);Linux宝库5t1F*} f4e,nsz
            (void) sprintf(p1,
ptN*@FX0                           "The f1 error occurred because of '%s'.",Linux宝库h%[ |#CA2g
                           explanation);
G"f C*v%r I0            local_log(p1);Linux宝库P6cE3SFc(kk!lBk
        }Linux宝库+r0ixip"F
  
您看到问题了吗?除非 local_log() 对 free() 释放的内存具有不寻常的响应能力,否则每次对 f1 的调用都会泄漏 100 字节。在记忆棒增量分发数兆字节内存时,一次泄漏是微不足道的,但是连续操作数小时后,即使如此小的泄漏也会削弱应用程序。Linux宝库5X6\!L/]jpP)U
Linux宝库o3nzQ,NN*|
在实际的 C 和 C++ 编程中,这不足以影响您对 malloc() 或 new 的使用,本部分开头的句子提到了“资源”不是仅指“内存”,因为还有类似以下内容的示例(请参见清单 2)。FILE 句柄可能与内存块不同,但是必须对它们给予同等关注:Linux宝库9J,ir [ [}7W g
Linux宝库7W(q @ m3en)d9E
Linux宝库!|c/jC R J&kh
清单 2. 来自资源错误管理的潜在堆内存丢失

CODE:

u6Qq4Jf0               
^:g)A j1Y6k!i0        int getkey(char *filename)Linux宝库*UiW`Ie jU
        {Linux宝库qZ/DF*c } W.j
            FILE *fp;Linux宝库+l-Amb`l.Dl_
            int key;Linux宝库Za?9ERJb

eO.Iwx*KdX0            fp = fopen(filename, "r");
U)YM F:jP0            fscanf(fp, "%d", &key);Linux宝库B | T1V&l
            return key;Linux宝库wt} ?+T*L(sYn2^f
        }Linux宝库O(l*h[;Ja
fopen 的语义需要补充性的 fclose。在没有 fclose() 的情况下,C 标准不能指定发生的情况时,很可能是内存泄漏。其他资源(如信号量、网络句柄、数据库连接等)同样值得考虑。
0aP o#Sg{6c#R0Linux宝库Jf;qe$|
内存错误分配Linux宝库wZ-mTS-a/e

)`+Ox'e9vq0错误分配的管理不是很困难。下面是一个示例(请参见清单 3):

CODE:Linux宝库&erIbk`'T!\S@S

清单 3. 未初始化的指针
%`CPT e0               
x!tuw [:c)S#my0        void f2(int datum)
a bu/XW X*C*^x0        {Linux宝库B q9ds1Fc*a#~
            int *p2;
{ggi1?0Linux宝库6\"^\#N,fPg\
                /* Uh-oh!  No one has initialized p2. */Linux宝库W"le4`#nU%P-^D
            *p2 = datum;
;JO%U3eCg0               ...Linux宝库FK[Z1^ |:D{x^
        }
关于此类错误的好消息是,它们一般具有显著结果。在 AIX? 下,对未初始化指针的分配通常会立即导致 segmentation fault 错误。它的好处是任何此类错误都会被快速地检测到;与花费数月时间才能确定且难以再现的错误相比,检测此类错误的代价要小得多。Linux宝库"{-z&D"M pBx,}
Linux宝库\Va\+pQ7W+E
在此错误类型中存在多个变种。free() 释放的内存比 malloc() 更频繁(请参见清单 4):
qlI5sX0
fp-p#dn:GT%F0
l] [izM*y'H5Q0清单 4. 两个错误的内存释放

CODE:

K7W%c0E-l3w0               Linux宝库$]'[%?r:pI}
        /* Allocate once, free twice. */Linux宝库%[;D'e jRG3{9pU
        void f3()Linux宝库/lqb_ jOE~)R/{8c
        {Linux宝库NoG-C%I.L6jDJ [
            char *p;Linux宝库$|Snk7uz

"u1z gHgl*j0            p = malloc(10);
5Ao-S~U)k"|apO0             ...Linux宝库X!QQw4d*T
            free(p);
3u6Nx{*r/F~W0             ...Linux宝库Hb@E-E_9\I
            free(p);Linux宝库p:f&r'N8V&H[
        }
9N3o@]2p'[x%n wT0Linux宝库?Sy5V9nY_
        /* Allocate zero times, free once. */Linux宝库0G {%W E^_~
        void f4()Linux宝库kQ-H(jr$v;\+@*k5QM
        {
h6D#t-|{%?U SD0            char *p;
p7?%po5{0
)]h#^0a/Nf O0                /* Note that p remains uninitialized here. */Linux宝库6H BNG A
            free(p);
#k'_0qH)W0        }Linux宝库 ]f%M9UJe~
这些错误通常也不太严重。尽管 C 标准在这些情形中没有定义具体行为,但典型的实现将忽略错误,或者快速而明确地对它们进行标记;总之,这些都是安全情形。
!M%E:z#Vs0Linux宝库t?JP1R!c4{*H
悬空指针Linux宝库1T s$U!T e:t

Gc9a%N6z mhsS0悬空指针比较棘手。当程序员在内存资源释放后使用资源时会发生悬空指针(请参见清单 5):
+s!h3Sw1]| rnrT0
a5g$n}Fo0
F7?-w2KkI0清单 5. 悬空指针

CODE:Linux宝库6C}w4aOE6s"\

               Linux宝库 R8u&[$_:b:sU
       void f8()
S,u4an4p"bm8K.o*F*_ F0       {Linux宝库}*j7yEC"y1I&wB
           struct x *xp;Linux宝库oxC'RJ*i$Y
Linux宝库5W'bdY?%f
           xp = (struct x *) malloc(sizeof (struct x));Linux宝库x$OL-[]'Z
           xp.q = 13;Linux宝库 Qnu*M3gXE4w
           ...
9h2Z'|7D;A3z gA1\V5q0           free(xp);
e3o~@y#Eq7C Z0           ...
&gW A+^G$K q0               /* Problem!  There's no guarantee thatLinux宝库(P5rb)n7e pG V
                  the memory block to which xp points
\1]8q#d6b'ls0                  hasn't been overwritten. */Linux宝库S&eU"Sf
           return xp.q;Linux宝库 D Sl'd#@8S~0^dY
       }
传统的“调试”难以隔离悬空指针。由于下面两个明显原因,它们很难再现:Linux宝库7?g!g oS0x.H{8L6a
Linux宝库3fe[BE:sT
即使影响提前释放内存范围的代码已本地化,内存的使用仍然可能取决于应用程序甚至(在极端情况下)不同进程中的其他执行位置。
}({:?/^t+?E0悬空指针可能发生在以微妙方式使用内存的代码中。结果是,即使内存在释放后立即被覆盖,并且新指向的值不同于预期值,也很难识别出新值是错误值。Linux宝库*FZ%Q8Jgy?\
悬空指针不断威胁着 C 或 C++ 程序的运行状态。
){ XsbU-Dxqj)S0Linux宝库7@.C8d-M^9|Q
数组边界违规
;{ DgZ'U8E7V%d~'cV0Linux宝库Q?h8mvQ(|6w
数组边界违规十分危险,它是内存错误管理的最后一个主要类别。回头看一下清单 1;如果 explanation 的长度超过 80,则会发生什么情况?回答:难以预料,但是它可能与良好情形相差甚远。特别是,C 复制一个字符串,该字符串不适于为它分配的 100 个字符。在任何常规实现中,“超过的”字符会覆盖内存中的其他数据。内存中数据分配的布局非常复杂并且难以再现,所以任何症状都不可能追溯到源代码级别的具体错误。这些错误通常会导致数百万美元的损失。
hH$H-EJ$u'Mt-O0Linux宝库F@!Jm&q~#k
内存编程的策略
m1V"v\$d0Linux宝库0R9m#p(a[2c
勤奋和自律可以让这些错误造成的影响降至最低限度。下面我们介绍一下您可以采用的几个特定步骤;我在各种组织中处理它们的经验是,至少可以按一定的数量级持续减少内存错误。Linux宝库&\T%V;U/Z[Nk
Linux宝库.M8uE-cc
编码风格Linux宝库4WA zQ E

{3ubHu mY]9~0编码风格是最重要的,我还从没有看到过其他任何作者对此加以强调。影响资源(特别是内存)的函数和方法需要显式地解释本身。下面是有关标头、注释或名称的一些示例(请参见清单 6)。Linux宝库'I0[$n g&th

Ft \~Cq(PE0Linux宝库%ev.xA0P
清单 6. 识别资源的源代码示例

CODE:

a WD(H&oJ@#{`R0     
w-^)u7@#S Ddp,W'`0        /********Linux宝库"bV E {~(| n
         * ...Linux宝库1~&X(Q8b+A~~w
         *Linux宝库;[a6T{[
         * Note that any function invoking protected_file_read()
GgP"Q(Z%z0u0         * assumes responsibility eventually to fclose() itsLinux宝库7k1M*t8L(EB~2J]
         * return value, UNLESS that value is NULL.
o%O*?t0\D l*v:z e+PH0         *Linux宝库?)R*b2a$E3C2i
         ********/
:S:B'sGAG,]"YA\D3p0        FILE *protected_file_read(char *filename)
x}(C*X:J0        {Linux宝库t9k-L7` H&R"_]q
            FILE *fp;Linux宝库&p2W KZ!{

-ML%k1Mo:q;_o0            fp = fopen(filename, "r");
:OX2ph^6WJ0            if (fp) {
xE2v]I!Q-w0                ...Linux宝库dNg-FB0~
            } else {
5OxJY$@!Y0                ...Linux宝库+\)_)E.R y
            }Linux宝库V%o(inK'C_ IKn
            return fp;Linux宝库j%saVF8u&|u d5W
        }
:o1~ H k gp~-J Y2X0Linux宝库-u8rh ~{
        /*******Linux宝库 @*Z$toJ[!k&h
         * ...Linux宝库~iVEP
         *
Zw WLA7v5xi8l4C0         * Note that the return value of get_message points to aLinux宝库2J+jB!h6zkm
         * fixed memory location.  Do NOT free() it; remember toLinux宝库6|-z^3Br KRq
         * make a copy if it must be retained ...Linux宝库$P`&TY-e|)`_h1F
         *Linux宝库8\8KP&~R `#[SI \0SM
         ********/
f$H(\i#s-c0        char *get_message()Linux宝库t#I5P3F!|z_9X
        {
:A^E2m3^p0w}0            static char this_buffer[400];
!l dd!C!n0Linux宝库)bEt$].MLl
            ...
Y8Fi ^G/s0            (void) sprintf(this_buffer, ...);Linux宝库1u]I p8i3k.~(G%yhB
            return this_buffer;
2Kwc2d `d0        }Linux宝库$\6r4Tfw p7^z
Linux宝库2k E+EAA K*F1p
Linux宝库/]/d1a/vM
        /********Linux宝库kNd-h~{
         * ...Linux宝库HKm:Xp
         * While this function uses heap memory, and soLinux宝库Qp-Y6\ZNJ&L
         * temporarily might expand the over-all memory
m@"W"xS5T`!W&Wy0         * footprint, it properly cleans up after itself.Linux宝库J)cW7NQ;G:_ L'b
         *
%No1B u^yH`-^0         ********/Linux宝库{%| U(Avd)\a
        int f6(char *item1)Linux宝库(hs[6`Ps6L `,sZ@
        {
#]|M9Pt T |0            my_class c1;Linux宝库G9vo r/kuf}*T
            int result;
/h7TZkn0            ...Linux宝库2Z\W-J-r~oU
            c1 = new my_class(item1);
/Nm.`k:@;wo0            ...
xfVm6bF9`0            result = c1.x;Linux宝库.i7|%h(A{+[
            delete c1;Linux宝库|]!M!cm~
            return result;
]%x1y)}Zj2v,M+p(X1i1N0        }
|Po2@)CX!l0        /********
3U*bI3S&g4yToH0v0         * ...Linux宝库U1ErG3i
         * Note that f8() is documented to return a valueLinux宝库C Hh#B1v2B
         * which needs to be returned to heap; as f7 thinlyLinux宝库}EDp2\\HH lw
         * wraps f8, any code which invokes f7() must beLinux宝库$Ay-|{e2e.c"k,Z#yv
         * careful to free() the return value.
*E+Y7`r-m@n0         *
f'Am!feu7l|0         ********/
z8G ?FG0        int *f7()Linux宝库v+u-o]5h`I]
        {Linux宝库7ov&I"S0?0n
            int *p;
t%ZQ:M2gS;~0
He;Zp)Q UlDyp0            p = f8(...);
ft!Z2f]{0            ...
Uz(U1aU;@,?0            return p;
1Nhx4^)?E0        }
T:~6KXj,a'?6S0     
使这些格式元素成为您日常工作的一部分。可以使用各种方法解决内存问题:
5y/{ }lmR0Linux宝库1G O`IZC8N+A
专用库
P| [1Y2Nj4PG#n0语言Linux宝库X,I/g];i7S
软件工具
g"b)Nni*}0硬件检查器
+i't0d K;M[0在这整个领域中,我始终认为最有用并且投资回报率最大的是考虑改进源代码的风格。它不需要昂贵的代价或严格的形式;可以始终取消与内存无关的段的注释,但影响内存的定义当然需要显式注释。添加几个简单的单词可使内存结果更清楚,并且内存编程会得到改进。Linux宝库R k#R/K;B D mt.z

n2pd^u0NL+Y&~9x6A0我没有做受控实验来验证此风格的效果。如果您的经历与我一样,您将发现没有说明资源影响的策略简直无法忍受。这样做很简单,但带来的好处太多了。Linux宝库n+a]$U!wv

C+zE-pH[*]J0检测
3U b*r.kw0sy V0
!LE`W*`0yv z0检测是编码标准的补充。二者各有裨益,但结合使用效果特别好。机灵的 C 或 C++ 专业人员甚至可以浏览不熟悉的源代码,并以极低的成本检测内存问题。通过少量的实践和适当的文本搜索,您能够快速验证平衡的 *alloc() 和 free() 或者 new 和 delete 的源主体。人工查看此类内容通常会出现像清单 7 中一样的问题。Linux宝库qP{%wBe1uf|'|
Linux宝库$F s*y#sN a[
Linux宝库+p:I3HgB|
清单 7. 棘手的内存泄漏

CODE:

r5t!p RU0           
0oG&z~ Y `"A b0        static char *important_pointer = NULL;Linux宝库P:y/a5VlKOn
        void f9()Linux宝库d g n6V#h
        {
@W/y'V4Iu)u0            if (!important_pointer)
G?#Z"E Ap8v@H0V0                important_pointer = malloc(IMPORTANT_SIZE);Linux宝库^(LZ#I/eh,QM,Yt&g
            ...Linux宝库G vG:T }N3M
            if (condition)
3Yw+}-Po0                    /* Ooops!  We just lost the referenceLinux宝库z4ST+v9elP1^ s
                       important_pointer already held. */Linux宝库U7A5lvfC+[/D
                important_pointer = malloc(DIFFERENT_SIZE);Linux宝库n o}_&ayT&j;SM:nT
            ...Linux宝库IJ6gUv&^hG
        }Linux宝库'~ Ne&WK9`
   
如果 condition 为真,简单使用自动运行时工具不能检测发生的内存泄漏。仔细进行源分析可以从此类条件推理出证实正确的结论。我重复一下我写的关于风格的内容:尽管大量发布的内存问题描述都强调工具和语言,对于我来说,最大的收获来自“软的”以开发人员为中心的流程变更。您在风格和检测上所做的任何改进都可以帮助您理解由自动化工具产生的诊断。
L/HP4iC&jH0Linux宝库 e[f K)g
静态的自动语法分析
-M[]J S{0
yNRY5HHW0当然,并不是只有人类才能读取源代码。您还应使静态语法分析 成为开发流程的一部分。静态语法分析是 lint、严格编译 和几种商业产品执行的内容:扫描编译器接受的源文本和目标项,但这可能是错误的症状。Linux宝库f:r BQ4Xg ceF!]

{'^t6g0|zJ|;B.H0希望让您的代码无 lint。尽管 lint 已过时,并有一定的局限性,但是,没有使用它(或其较高级的后代)的许多程序员犯了很大的错误。通常情况下,您能够编写忽略 lint 的优秀的专业质量代码,但努力这样做的结果通常会发生重大错误。其中一些错误影响内存的正确性。与让客户首先发现内存错误的代价相比,即使对这种类别的产品支付最昂贵的许可费也失去了意义。清除源代码。现在,即使 lint 标记的编码可能向您提供所需的功能,但很可能存在更简单的方法,该方法可满足 lint,并且比较强键又可移植。
v(^V\!I:m0
1]*P;z {MY0内存库
/n s+BPq0
T5psS\&y8x^s0补救方法的最后两个类别与前三个明显不同。前者是轻量级 的;一个人可以容易地理解并实现它们。另一方面,内存库和工具通常具有较高的许可费用,对部分开发人员来说,它们需要进一步完善和调整。有效地使用库和工具的程序员是理解轻量级的静态 方法的人员。可用的库和工具给人的印象很深:其作为组的质量很高。但是,即使最优秀的编程人员也可能会被忽略内存管理基本原则的非常任性的编程人员搅乱。据我观察,普通的编程人员在尝试利用内存库和工具进行隔离工作时也只能感到灰心。
;kv#xa1NA[:T0Linux宝库{/f+I YC*\T C ?TJ
由于这些原因,我们催促 C 和 C++ 程序员为解决内存问题先了解一下自己的源。在这完成之后,才去考虑库。
N W.h,Z,t0
.|/dK FS0使用几个库能够编写常规的 C 或 C++ 代码,并保证改进内存管理。Jonathan Bartlett 在 developerWorks 的 2004 评论专栏中介绍了主要的候选项,可以在下面的参考资料部分获得。库可以解决多种不同的内存问题,以致于直接对它们进行比较是非常困难的;这方面的常见主题包括垃圾收集、智能指针 和 智能容器。大体上说,库可以自动进行较多的内存管理,这样程序员可以犯更少的错误。
9`;orO3a7~0
%G$nRpc0我对内存库有各种感受。他们在努力工作,但我看到他们在项目中获得的成功比预期要小,尤其在 C 方面。我尚未对这些令人失望的结果进行仔细分析。例如,业绩应该与相应的手动 内存管理一样好,但是这是一个灰色区域——尤其在垃圾收集库处理速度缓慢的情况下。通过这方面的实践得出的最明确的结论是,与 C 关注的代码组相比,C++ 似乎可以较好地接受智能指针。
'iYY}:AH,n0Linux宝库\ps E6nf1g!V
内存工具Linux宝库0k7hx1B9rvZ0w
Linux宝库 {x\Nw
开发真正基于 C 的应用程序的开发团队需要运行时内存工具作为其开发策略的一部分。已介绍的技术很有价值,而且不可或缺。在您亲自尝试使用内存工具之前,其质量和功能您可能还不了解。
9E;Bf:v)IR L0
ew?y+a*QxZ0本文主要讨论了基于软件的内存工具。还有硬件内存调试器;在非常特殊的情况下(主要是在使用不支持其他工具的专用主机时)才考虑它们。Linux宝库h-T|&H-d| R

3o {-UJ3A1g0市场上的软件内存工具包括专有工具(如 IBM Rational? Purify 和 Electric Fence)和其他开放源代码工具。其中有许多可以很好地与 AIX 和其他操作系统一起使用。Linux宝库s;C-U m8Hx
Linux宝库F)_t`:nv SUL'l~
所有内存工具的功能基本相同:构建可执行文件的特定版本(很像在编译时通过使用 -g 标记生成的调试版本)、练习相关应用程序和研究由工具自动生成的报告。请考虑如清单 8 所示的程序。Linux宝库*jeqX2W%l7j|+a W

]H?;l9j0Linux宝库 M,zp/J.dGb
清单 8. 示例错误

CODE:Linux宝库f:CK%Dr+C!Z

              Linux宝库Rp|#p,Y
        int main()
FY*|wk0        {
I+}e!nu/EU6N0            char p[5];
l V{lx1bq0            strcpy(p, "Hello, world.");
W%L1O/_G9{-^%B2_6A0            puts(p);
|?*?8pf6Q^0        }
_$T(N {7X Za0
此程序可以在许多环境中“运行”,它编译、执行并将“Hello, world.\n”打印到屏幕。使用内存工具运行相同应用程序会在第四行产生一个数组边界违规的报告。在了解软件错误(将十四个字符复制到了只能容纳五个字符的空间中)方面,这种方法比在客户处查找错误症状的花费小得多。这是内存工具的功劳。
lL8x7tj-D vd%Q%Z0Linux宝库%^_8a GQ1p b
    作为一名成熟的 C 或 C++ 程序员,您认识到内存问题值得特别关注。通过制订一些计划和实践,可以找到控制内存错误的方法。学习内存使用的正确模式,快速发现可能发生的错误,使本文介绍的技术成为您日常工作的一部分。您可以在开始时就消除应用程序中的症状,否则可能要花费数天或数周时间来调试。
Linux宝库J#Q7M5[1K9d

L0lx:z1o7k0[本帖最后由 westsoftware 于 2008-3-23 13:42 编辑]

TAG:

cugbcat发布于2008-03-24 17:33:40
这些不能算是难点,在长时间运行的情况下,保证服务器代码不内存泄漏、不越界,这是基本要求。
root1982发布于2008-03-27 11:31:54
而且现在有很多东西可以帮助程序员发现问题。Linux论坛 w        yD*{8q:dJ
比如dmalloc
hyxc007发布于2008-03-27 17:19:11
应该没什么的,只要自己好好学习!
linux_happy发布于2008-04-30 21:45:36
顶一下!
Linux生活 linuxpk 发布于2008-06-18 15:19:30
解释非常详细,谢谢!
linux_happy发布于2008-06-18 15:58:02
仔细看了下,很值得仔细的研究一下
西部软件部落 westsoftware 发布于2008-06-18 20:28:52
其实这些东西以前感觉没什么。。不就是内存开辟与释放吗? H!k)A'D^(sp/N7Vvn
很简单???Linux宝库1A!hT-]        w^6w
当你在大型项目里的时候,你开发出的软件,运行的时候占用内存越来越大。。??
+c}7wn
o;g U
到了这个时候,你就应该好好看看这篇文章。。。
Linux,开源,开源论坛"m5ak7D]9p
看起来简单,你并不一定能做到内存这方面的完美。
-ay3a2B;d!FU\Linux宝库这篇文章很值得一看。。。
Linux论坛
|^q,Fd


西部软件部落 westsoftware 发布于2008-06-18 20:36:59
从这个问题可以引申到相应的BUS_ERROR问题。。
锅盖头的个人空间 锅盖头 发布于2008-06-19 07:16:58
顶一下 呵呵
zyszys发布于2008-06-20 17:23:17
初学者应该注意的……还是顶一下
ghosTM55发布于2008-06-21 09:19:27
学习了
laughing_hys发布于2008-07-04 20:33:01
回复 1楼 westsoftware 的帖子
呵呵,看标题的时候想应该是说内存问题。果然Linux论坛?U]%Z.ClB&I
平时养成习惯就好了。
YC        A'r?;`/T+rLinux论坛内存错误这种bug很难复现,查找这种bug会降低生活幸福指数的,呵呵
&q K4C(O"M%`全球最火中文开源论坛关键是要有内存管理意识,写代码的时候只要用到数组指针就特别小心就行了
newborn发布于2008-07-08 18:48:22
跟习惯有更多的关系吧。。
plaispool发布于2008-07-17 20:25:54
先顶了!
zkeey发布于2008-07-30 09:46:49
值得重视!
zcl895474962发布于2008-08-01 23:31:43
关于内存的问题
        FU^        eg7eW,nLinux论坛
2zR7Y:A3Z,[`Linux宝库以前还没看着方面的资料啊全球最火中文开源论坛V{,zZ,Xy;]t8g
Linux宝库        IERl)jf$f(ul
谢谢了

g8A&t5H:L/v6j
`)}r-PpQ1d#B
就是字体的颜色有点让人不好受
tpli发布于2008-09-23 12:27:49
支持  坚决支持。。
我来说两句

(可选)

westsoftware

westsoftware

本博客与某些软件公司没有任何关系,纯属个人博客。

数据统计

  • 访问量: 5917
  • 日志数: 8
  • 图片数: 1
  • 建立时间: 2007-03-27
  • 更新时间: 2008-06-03

RSS订阅

Open Toolbar