青岛 网站科技公司微信开发公司
- 作者: 五速梦信息网
- 时间: 2026年03月21日 09:55
当前位置: 首页 > news >正文
青岛 网站科技公司,微信开发公司,网站建设与管理实践心得,wordpress怎么修改栏目标题说明#xff1a; 这是个人对该在Linux平台上的C语言学习网站笨办法学C上的每一个练习章节附加题的解析和回答 ex1: 在你的文本编辑器中打开ex1文件#xff0c;随机修改或删除一部分#xff0c;之后运行它看看发生了什么。 vim ex1.c打开 ex1.c 文件。假如我们删除 return 0…说明 这是个人对该在Linux平台上的C语言学习网站笨办法学C上的每一个练习章节附加题的解析和回答 ex1: 在你的文本编辑器中打开ex1文件随机修改或删除一部分之后运行它看看发生了什么。 vim ex1.c打开 ex1.c 文件。假如我们删除 return 0; 这一行代码保存文件后在命令行中进入该文件所在目录然后尝试运行程序执行 ./ex1 命令前提是之前已经成功编译生成了 ex1 可执行文件。 结果根据 C 语言程序的运行机制main 函数如果没有显式的 return 语句在大多数实现中函数执行结束时会隐式返回一个默认值通常是 0但这依赖于具体编译器实现。而在运行时由于程序逻辑本身没有依赖 return 值去做进一步操作所以程序可能依然能够输出 Hello world.看起来好像正常运行了但从代码规范性角度是存在问题的。 再多打印5行文本或者其它比Hello world.更复杂的东西。 跳过 执行man 3 puts来阅读这个函数和其它函数的文档。 命令行中会显示 puts 函数的详细文档信息包括函数的功能描述例如它用于向标准输出设备输出字符串并自动在末尾添加一个换行符、函数的原型int puts(const char s);、函数的参数说明s 参数是要输出的字符串指针、函数的返回值含义成功时返回一个非负整数出错时返回 EOF等内容。同时在该手册页中还会列出与之相关的其他一些函数比如 printf、fputs 等函数的简单介绍和参考位置 ex2: 创建目标all:ex1可以以单个命令make构建ex1。 CFLAGS-Wall -gall: ex1clean:rm -f ex1ex1: ex1.ccc \((CFLAGS) ex1.c -o ex1 在 Makefile 里定义了 all 这个目标并且让它依赖于 ex1这意味着当执行 make 命令时如果没有 指定具体目标默认会执行 Makefile 里的第一个目标或者由 .DEFAULT_GOAL 指定的目标这里添加 all 目标后通常就会执行它make 会先检查 ex1 是否需要更新例如其依赖的 ex1.c 文件是否有修改 等情况如果需要更新就会执行 ex1 目标下定义的构建命令即 cc \)(CFLAGS) ex1.c -o ex1来生 成 ex1 文件这样就实现了通过单个 make 命令来构建 ex1 的功能。 阅读man make来了解关于如何执行它的更多信息。 跳过 阅读man cc来了解关于-Wall和-g行为的更多信息。 -Wall会详细说明它启用的具体警告类别解释不同警告所对应的代码潜在问题类型比如变量未使用 、类型不兼容、隐式函数声明等各种情况产生的警告。而对于 -g会讲解它如何在生成的可执行文件中 嵌入调试信息像调试符号的存储格式、在使用调试工具如 gdb时如何利用这些调试信息来定位代码中的问题例如查看变量值、跟踪函数调用流程等操作如何基于这些调试符号实现等内容。 在互联网上搜索Makefile文件看看你是否能改进你的文件。 找到文件如下 CC gcc # 指定编译器 CFLAGS -Wall -Wextra -g # 执行的make命令的可选选项-Wall 表示启用所有警告-Wextra 是额外的警告选项会进一步给出更多类型的警告信息-g 选项用于在生成的目标文件中添加调试信息方便后续使用调试工具如 gdb来调试程序 LDFLAGS -lm # 用于指定链接阶段的选项-lm 表示要链接数学库libm SRC $(wildcard src/.c) # 使用 wildcard 函数来查找 src 目录下所有以 .c 为后缀的源文件 OBJ \((SRC:.c.o) # 变量替换将 SRC 变量中每个文件名的后缀 .c 替换为 .o从而得到对应的目标文件 TARGET myprogram # 定义了最终要生成的可执行文件的名称为 myprogram.PHONY: all clean # 声明 all 和 clean 为伪目标。伪目标并不对应实际的文件而是代表一些操作或者规则; 用伪目标可以避免与可能存在的同名文件产生冲突保证规则正常执行all: \)(TARGET) #定义了 all 这个目标依赖于 \((TARGET)\)(TARGET): \((OBJ)\)(CC) \((CFLAGS) -o \) \(^ \)(LDFLAGS) # \(代表当前规则的目标,这里为\)(TRAGET);\(^ 表示所有依赖,在这里就是所有的 .o 文件; -o 选项为指定生成文件名称%.o: %.c # 将所有.c 文件依赖.o 文件\)(CC) \((CFLAGS) -c -o \) \( # \) 表示第一个依赖在这里就是对应的 .c 源文件clean:rm -f \((OBJ) \)(TARGET)在另一个C语言项目中找到Makefile文件并且尝试理解它做了什么。 在github上找了一个开源的项目nginx/nginx: The official NGINX Open Source repository.的Makefile的内容如下 # Compiler and linker settings CC cc CFLAGS -O2 -pipe -Wall # -O2 一种优化级别选项它指示编译器对代码进行一定程度的优化以提高生成的可执行文件的运行效率;-pipe 让编译器在编译过程中使用管道来传递中间结果这样可以加快编译速度 LDFLAGS # 用于指定链接阶段的选项这里为空表示暂时没有额外添加特定的链接相关设置# Targets all: buildbuild:\((CC) \)(CFLAGS) -o nginx src/*.c \((LDFLAGS) # src 目录下所有的 .c 源文件进行编译然后通过 -o nginx 将生成的可执行文件命名为 nginxclean:rm -f nginx *.o # 强制删除名为 nginx 的可执行文件以及所有后缀为 .o 的目标文件ex3: 找到尽可能多的方法使ex3崩溃。 改变格式化占位符与参数类型不匹配 将 printf(I am %d years old.\n, age); 中的 %d 改为 %s像这样 printf(I am %s years old.\n, age);然后重新编译运行。由于 %s 期望传入的是字符串指针类型的参数而这里传入的是 int 类型的 age编译器会给出类型不匹配相关警告。 传入的参数个数少于格式化字符串中占位符个数 修改 printf 语句为 printf(I am %d years %d old\n, age);也就是在格式字符串中多写了一个 %d 占位符但只传入了一个 age 参数。重新编译时编译器会提示参数数量不足的警告运行时程序输出结果会是错误的可能会输出一些随机的数值来填充多余的占位符对应的位置导致输出不符合预期甚至可能因非法内存访问等原因而崩溃。 格式化字符串中使用非法的转义序列 把 printf(I am %d years old.\n, age); 中的 \n 改为比如 \z\z 不是合法的转义序列变成 printf(I am %d years old.\z, age);编译时编译器可能会给出关于非法转义序列的警告。 执行man 3 printf来阅读其它可用的%格式化占位符。如果你在其它语言中使用过它们应该看着非常熟悉它们来源于printf。 除了常见的 %d用于输出十进制整数、%s用于输出字符串外还有比如 %f用于输出浮点数例如 float num 3.14; printf(The number is: %f\n, num); 可以将浮点数 num 的值以常规的小数形式输出。 %c用于输出单个字符像 char ch A; printf(The character is: %c\n, ch); 能输出字符 A。 %x 或 %X分别用于以十六进制小写形式和大写形式输出整数例如 int hex_num 255; printf(The hex number is: %x\n, hex_num); 会输出 ff以小写十六进制展示整数 255 的值若使用 %X 则会输出 FF。 %o用于以八进制形式输出整数如 int oct_num 10; printf(The octal number is: %o\n, oct_num); 会输出 12八进制下 10 的表示。 %p用于输出指针的值以十六进制形式展示内存地址例如 int *ptr num; printf(The pointer address is: %p\n, ptr); 可以输出 ptr 指针所指向的内存地址十六进制格式。 手册页里还会介绍每个占位符对应的可选修饰符比如设置宽度、精度、对齐方式等内容帮助更灵活准确地进行格式化输出。 将ex3添加到你的Makefile的all列表中。到目前为止可以使用make clean all来构建你所有的练习。 添加all: ex1 ex3 将ex3添加到你的Makefile的clean列表中。当你需要的时候使用make clean可以删除它。 添加: clean:rm -f ex1 ex3 ex4: 安装 Valgrind说明 教学网站中的讲义下载Valgrind链接已经失效了所以使用最新的版本的下载地址 curl -O https://sourceware.org/pub/valgrind/valgrind-3.24.0.tar.bz2按照上面的指导使用Valgrind和编译器修复这个程序。 我运行程序错误信息如下 \) valgrind ./ex4 19914 Memcheck, a memory error detector 19914 Copyright © 2002-2024, and GNU GPLd, by Julian Seward et al. 19914 Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info 19914 Command: ./ex4 19914 ^[[BI am -16778024 years old. 19914 Conditional jump or move depends on uninitialised value(s) 19914 at 0x48D70BB: __printf_buffer (vfprintf-process-arg.c:58) 19914 by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) 19914 by 0x48CD1A2: printf (printf.c:33) 19914 by 0x109188: main (ex4.c:9) 19914 19914 Use of uninitialised value of size 8 19914 at 0x48CC0AB: _itoa_word (_itoa.c:183) 19914 by 0x48D6C8B: __printf_buffer (vfprintf-process-arg.c:155) 19914 by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) 19914 by 0x48CD1A2: printf (printf.c:33) 19914 by 0x109188: main (ex4.c:9) 19914 19914 Conditional jump or move depends on uninitialised value(s) 19914 at 0x48CC0BC: _itoa_word (_itoa.c:183) 19914 by 0x48D6C8B: __printf_buffer (vfprintf-process-arg.c:155) 19914 by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) 19914 by 0x48CD1A2: printf (printf.c:33) 19914 by 0x109188: main (ex4.c:9) 19914 19914 Conditional jump or move depends on uninitialised value(s) 19914 at 0x48D6D79: __printf_buffer (vfprintf-process-arg.c:186) 19914 by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) 19914 by 0x48CD1A2: printf (printf.c:33) 19914 by 0x109188: main (ex4.c:9) 19914 I am 31 inches tall. 19914 19914 HEAP SUMMARY: 19914 in use at exit: 0 bytes in 0 blocks 19914 total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated 19914 19914 All heap blocks were freed – no leaks are possible 19914 19914 Use –track-originsyes to see where uninitialised values come from 19914 For lists of detected and suppressed errors, rerun with: -s 19914 ERROR SUMMARY: 6 errors from 4 contexts (suppressed: 0 from 0) 检测到的问题总结 Conditional jump or move depends on uninitialised value“条件跳转或移动操作依赖于未初始化的值” Use of uninitialised value of size 8“使用了大小为 8 字节的未初始化值” 这些问题表明某个变量在被正确初始化之前就被使用了这会导致不可预测的行为 at 0x48CC0AB: _itoa_word (_itoa.c:183) at 0x48D70BB: __printf_buffer (vfprintf-process-arg.c:58) by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) by 0x48CD1A2: printf (printf.c:33) by 0x109188: main (ex4.c:9) 表明错误出现在程序ex4.c的main函数中具体在第 9 行特别是在printf调用期间。 栈追踪信息显示错误源于标准库中的vfprintf-process-arg.c和_itoa.c文件这表明问题出在printf函数的格式化或参数处理方面。使用Valgrind调试修复的这个程序 Use –track-originsyes to see where uninitialised values come from 这是Valgrind 给出的提示 使用–track-originsyes选项来确定未初始化值的确切来源。 \( valgrind --track-originsyes./ex4 valgrind: no program specified valgrind: Use --help for more information. Lin:~/ysyx/ysyx-workbench/learn_record/C_Linux/ex4\) valgrind –track-originsyes ./ex4 21270 Memcheck, a memory error detector 21270 Copyright © 2002-2024, and GNU GPLd, by Julian Seward et al. 21270 Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info 21270 Command: ./ex4 21270 I am -16778024 years old. 21270 Conditional jump or move depends on uninitialised value(s) 21270 at 0x48D70BB: __printf_buffer (vfprintf-process-arg.c:58) 21270 by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) 21270 by 0x48CD1A2: printf (printf.c:33) 21270 by 0x109188: main (ex4.c:9) 21270 Uninitialised value was created by a stack allocation 21270 at 0x109149: main (ex4.c:4) 21270 21270 Use of uninitialised value of size 8 21270 at 0x48CC0AB: _itoa_word (_itoa.c:183) 21270 by 0x48D6C8B: __printf_buffer (vfprintf-process-arg.c:155) 21270 by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) 21270 by 0x48CD1A2: printf (printf.c:33) 21270 by 0x109188: main (ex4.c:9) 21270 Uninitialised value was created by a stack allocation 21270 at 0x109149: main (ex4.c:4) 21270 21270 Conditional jump or move depends on uninitialised value(s) 21270 at 0x48CC0BC: _itoa_word (_itoa.c:183) 21270 by 0x48D6C8B: __printf_buffer (vfprintf-process-arg.c:155) 21270 by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) 21270 by 0x48CD1A2: printf (printf.c:33) 21270 by 0x109188: main (ex4.c:9) 21270 Uninitialised value was created by a stack allocation 21270 at 0x109149: main (ex4.c:4) 21270 21270 Conditional jump or move depends on uninitialised value(s) 21270 at 0x48D6D79: __printf_buffer (vfprintf-process-arg.c:186) 21270 by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) 21270 by 0x48CD1A2: printf (printf.c:33) 21270 by 0x109188: main (ex4.c:9) 21270 Uninitialised value was created by a stack allocation 21270 at 0x109149: main (ex4.c:4) 21270 I am 31 inches tall. 21270 21270 HEAP SUMMARY: 21270 in use at exit: 0 bytes in 0 blocks 21270 total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated 21270 21270 All heap blocks were freed – no leaks are possible 21270 21270 For lists of detected and suppressed errors, rerun with: -s 21270 ERROR SUMMARY: 6 errors from 4 contexts (suppressed: 0 from 0)Why is the result no different from the command valgrind without –track-originsyes 发现多了一个错误信息 Uninitialised value was created by a stack allocation at 0x109149: main (ex4.c:4) Valgrind 指出程序中正在使用一个未初始化的变量。在代码中的特定行ex4.c文件里有效代码的第 4 行并且这个错误是在main函数中出现的包含了一个在栈上分配但在使用前未被初始化的变量。 观察代码文件ex4.c中内容 值得一提的是在 C 语言代码中行号计数通常是从 1 开始按顺序依次递增的这里说的行号计数递增是是从整个源文件的角度去数的有效代码行号空行不算也就是包含了前面的头文件引入#include stdio.h 算第 1 行以及 main 函数的定义那一行int main() 算第 3 行之后int height; 所在的那一行就是第 4 行了 by 0x109188: main (ex4.c:9) at 0x109149: main (ex4.c:4) at部分是在追溯未初始化值的起源也就是变量在内存中最初分配创建的位置。它告诉我们这个未初始化的隐患是从哪里开始的在这个例子中就是变量height被声明的那一行。 by部分是在指出错误发生的位置即程序在执行到哪一行代码时因为使用了这个未初始化的值而触发了错误。这是实际产生错误行为的代码位置。 这里by使用的从代码文本编辑器显示的相对行数角度指的是printf(I am %d inches tall.\n, height);这一行而错误的起源at使用的从整个源文件绝对行号的角度指的是int height;这一行根据错误信息Uninitialised value was created by a stack allocation未初始化值是通过栈分配产生的给int height赋值从而解决改错误信息。 对于Valgrind 侧重于检测与内存访问相关的错误例如使用未初始化的内存、无效的内存读 / 写操作或内存泄漏等情况。如果代码包含逻辑错误或与内存访问无关的问题Valgrind 不会对其进行标记。所以对于printf(I am %d years old.\n);缺少参数的情况我们使用编译器可以轻松检查出错误问题 $ make -f ../ex2/Makefile ex4 cc -Wall -g ex4.c -o ex4 ex4.c: In function ‘main’: ex4.c:8:19: warning: format ‘%d’ expects a matching ‘int’ argument [-Wformat]8 | printf(I am %d years old.\n);| ~^| || int ex4.c:5:9: warning: unused variable ‘age’ [-Wunused-variable]5 | int age 10;| ^~~至此我们通过使用Valgrind和编译器修复了这个程序。 在互联网上查询Valgrind相关的资料。Valgrind 官方首页这里是获取 Valgrind 最新信息的权威来源包含了 Valgrind 的当前版本、支持的平台、近期新闻等内容。例如你可以了解到 2024 年 10 月 31 日发布的 Valgrind-3.24.0 版本所支持的众多操作系统和硬件架构等信息 。Valgrind 官方文档页面详细介绍了 Valgrind 的各种工具、使用方法、命令行选项等是深入学习和使用 Valgrind 的必备参考。比如关于 Memcheck 工具的详细介绍包括它能够检测的各种内存错误类型如使用未初始化的内存、内存泄漏等以及相关的命令行选项如–leak-check的具体用法等都有详细说明. 下载另一个程序并手动构建它。尝试一些你已经使用但从来没有手动构建的程序。 参考如下; # 下载源码的归档文件来获得源码
解压归档文件将文件提取到你的电脑上
运行./configure来建立构建所需的配置
运行make来构建源码就像之前所做的那样
运行sudo make install来将它安装到你的电脑# 1) Download it (use wget if you dont have curl)
curl -O http://valgrind.org/downloads/valgrind-3.6.1.tar.bz2# use md5sum to make sure it matches the one on the site md5sum valgrind-3.6.1.tar.bz2# 2) Unpack it. tar -xjvf valgrind-3.6.1.tar.bz2# cd into the newly created directory cd valgrind-3.6.1# 3) configure it ./configure# 4) make it make# 5) install it (need root) sudo make install 看看Valgrind的源码是如何在目录下组织的并且阅读它的Makefile文件。不要担心这对我来说没有任何意义。 Valgrind 的源码目录组织大概是这样的有 coregrind 目录这里面包含了它的核心功能实现代码像内存管理以及错误检测等相关代码是整个 Valgrind 的核心引擎所在。include 目录存放着 Valgrind 的头文件定义了各种数据结构、函数接口这些内容方便其他模块或者外部程序去引用。还有像 memcheck 目录实现的是 Memcheck 工具的具体逻辑能检测内存泄漏、越界访问等内存相关错误。cachegrind 目录包含的是 Cachegrind 工具代码用于分析程序缓存使用情况来辅助优化性能。callgrind 目录里放着 Callgrind 工具相关代码可分析程序调用图、函数调用关系以及收集相关性能数据。另外有 docs 目录存着文档像用户手册、技术文档之类的方便大家了解使用 Valgrindtests 目录包含各种测试用例用来测试验证 Valgrind 功能保证其正确稳定。 Valgrind 是通过运行 “./configure” 命令能指定像 “–prefix” 设置安装目录、“–host” 指定目标主机类型等参数。“./configure” 运行完就会生成 “Makefile” 文件这个文件里有编译、链接等构建规则指导 “make” 命令怎么构建 Valgrind。然后执行 “make” 命令进行编译按规则把源文件编译成目标文件和可执行文件最后用 “make install” 命令把编译好的文件安装到指定的安装目录下。 阅读它的 Makefile 文件的话里面就是那些具体的编译、链接规则还有依赖关系等内容不同部分对应不同工具或者功能模块的构建相关设定
- 上一篇: 青岛 网站建设昆明360网站制作
- 下一篇: 青岛 网站设计襄阳seo
相关文章
-
青岛 网站建设昆明360网站制作
青岛 网站建设昆明360网站制作
- 技术栈
- 2026年03月21日
-
青岛 html5flash设计开发丨交互设计丨网站建设温州人才网招聘网官网
青岛 html5flash设计开发丨交互设计丨网站建设温州人才网招聘网官网
- 技术栈
- 2026年03月21日
-
沁县网站建设360建筑网兼职
沁县网站建设360建筑网兼职
- 技术栈
- 2026年03月21日
-
青岛 网站设计襄阳seo
青岛 网站设计襄阳seo
- 技术栈
- 2026年03月21日
-
青岛 网站制作公司苏州网站开发的企业
青岛 网站制作公司苏州网站开发的企业
- 技术栈
- 2026年03月21日
-
青岛 正规网站空间wordpress4.9.6中文版
青岛 正规网站空间wordpress4.9.6中文版
- 技术栈
- 2026年03月21日






