很容易理解这样的代码是如何工作的:
#include <string.h>
#define strcmp my_strcmp
int my_strcmp(const char *, const char *)
...
strcmp(str1, str2);
...
Run Code Online (Sandbox Code Playgroud)
但这个问题是这在技术上是否正确.
从C11:
7.1.3.1(关于保留名称):
...
- 如果包含任何相关标头,则保留以下任何子条款中的每个宏名称(包括未来的库方向)以供指定使用; 除非另有明确说明(见7.1.4).
- 在以下任何子条款(包括未来的库方向)和errno中具有外部链接的所有标识符始终保留用作具有外部链接的标识符.184)
- 在以下任何子条款中列出的具有文件范围的每个标识符(包括未来的库方向)保留用作宏名称,并且如果包括任何相关联的标题,则用作具有相同名称空间的文件范围的标识符.
184具有外部链接的保留标识符列表包括math_errhandling,setjmp,va_copy和va_end.
所以这意味着这strcmp是一个保留字,因为string.h包括在内.
7.1.3.2:
...如果程序在保留它的上下文中声明或定义标识符(7.1.4允许的除外),或者将保留标识符定义为宏名称,则行为未定义.
现在这似乎说重新定义strcmp是未定义的行为,除了它在7.1.4中以某种方式允许.
7.1.4可能相关的内容是:
7.1.4.1:
...标头中声明的任何函数可以另外实现为标头中定义的类函数宏,因此如果在包含标头时显式声明了库函数,则可以使用下面显示的技术之一来确保声明不受这种宏的影响.通过将函数的名称括在括号中,可以在本地抑制函数的任何宏定义,因为该名称后面没有左括号,后面表示宏函数名称的扩展.出于相同的语法原因,即使它也被定义为宏,也允许获取库函数的地址.185)使用#undef删除任何宏定义也将确保引用实际函数....
185这意味着实现应为每个库函数提供实际函数,即使它还为该函数提供宏.
7.1.4.2:
如果可以在不引用标头中定义的任何类型的情况下声明库函数,则允许声明该函数并使用它而不包括其关联的标头.
其余条款无关紧要.我没有看到7.1.3.2指的是"7.1.4允许的",除了与函数相同的头中的库函数的定义,即标准头,作为宏.
总之,上面的代码是技术上未定义的行为吗?如果string.h不包括在内怎么样?
我需要#define在大约300个.c文件的顶部包含一个.我宁愿不更改代码,因为它是开源代码,但如果我必须,我将只编写一个脚本来修改所有文件.有没有办法#define在编译期间使用gcc在每个源文件的顶部添加一个或头文件include?这#define是:
#define malloc MYmalloc
Run Code Online (Sandbox Code Playgroud) 我需要一些关于向被调用方"转发"参数的建议(在LLVM-IR中).
假设我有一个在模块F中所有其他函数开头调用的函数.从F我需要访问(读取)传递给其直接调用者的参数.
现在要做到这一点,我在结构中的调用者中包含所有参数,并将i8*指针传递给结构F,以及一个标识符,告诉调用哪个调用者F.F然后有一个巨大的开关,分支到适当的拆箱代码.必须这样做,因为模块中的函数具有不同的签名(不同的参数/返回值计数和类型;甚至不同的调用约定),但它显然是次优的(从性能和代码大小的角度来看)因为我需要在堆栈上分配结构,复制其中的参数,传递一个额外的指针F,然后执行拆箱.
我想知道是否有更好的方法来做到这一点,即从函数访问其直接调用者的堆栈帧的方法(知道,由于标识符,调用函数的调用者),或者更一般地,任意在其直接调用者中定义的值.有什么建议?
注意:我正在研究的重点是拥有完成所有这一切的单一功能F; 拆分/内联/专门化/模板化F不是一种选择.
澄清一下,假设我们有以下功能FuncA和FuncB(注意:以下只是伪C代码,永远记住我们在谈论LLVM-IR!)
Type1 FuncA(Type2 ArgA1) {
F();
// ...
}
Type3 FuncB(Type4 ArgB1, Type5 ArgB2, Type6 ArgB3) {
F();
// ...
}
Run Code Online (Sandbox Code Playgroud)
我需要的是一个有效的方法F来执行以下功能:
void F() {
switch (caller) {
case FuncA:
// do something with ArgA1
break;
case FuncB:
// do something with …Run Code Online (Sandbox Code Playgroud) 该Matasano博客呼吁"检查的返回值malloc()"一"C程序反成语."相反malloc()应该自动调用abort()如果失败了你.这个论点是,因为如果malloc()失败,你通常会想要中止程序,这应该是默认行为,而不是你必须费力地键入的东西 - 或者可能忘记输入!-every time.
没有深入了解这个想法的优点,最简单的方法是什么?我正在寻找能够自动检测其他库函数的内存分配失败的东西asprintf().便携式解决方案会很精彩,但我也会对特定于mac的东西感到满意.
总结下面的最佳答案:
MallocErrorAbort=1在运行程序之前设置环境变量.自动适用于所有内存分配功能.
使用动态库填充malloc()程序在运行时使用LD_PRELOAD或加载自定义包装器DYLD_INSERT_LIBRARIES.你可能会想包装calloc(),realloc(),和温度.同样.
定义您自己的malloc()和free()功能,并使用dyld(RTLD_NEXT, "malloc") 此处所示访问系统版本.同样,你可能会想包装calloc(),realloc(),和温度.同样.
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
void *(*system_malloc)(size_t) = NULL;
void* malloc(size_t bytes) {
if (system_malloc == NULL) {
system_malloc = dlsym(RTLD_NEXT, "malloc");
}
void* ret = system_malloc(bytes);
if …Run Code Online (Sandbox Code Playgroud) 我想计算程序中内存分配调用(malloc、calloc、new ...)的数量。该程序积极使用 STL 容器。主要目的是计算所有这些容器内的内存分配。稍后我将使用这些信息来优化性能。我的程序是用 C++ 编写的,在 Linux 下运行。有什么工具可以做到吗?
我可以做这样的事情吗:
#ifdef FREERTOS
#define malloc(size) pvPortMalloc(size)
#define free(ptr) pvPortFree(ptr)
#endif
Run Code Online (Sandbox Code Playgroud)
并期望它总是调用pvPortMalloc()而不是malloc()?
另外,把它放在之前/之后会有什么区别#include <stdlib.h>?
我有一些代码想要在 FreeRTOS 内和外运行,我想将所有调用替换为使用 FreeRTOS 时的malloc()调用pvPortMalloc()。
我在 Linux 上有一个 C++ 应用程序。在程序的整个执行过程中,我如何才能看到对函数的库调用malloc(),然后是系统调用,例如sbrk()等等?
我希望这能显示哪些 libc 函数发生并负责后续的 Linux 系统调用。
注意:我不想拦截任何函数调用,只是记录哪些 C 库函数调用了哪些系统调用。
我想替换默认的 malloc 并添加一些统计信息以及泄漏检测和 malloc 函数的其他行为。我见过一些其他的实现,比如 gperftool 和 jemlloc。他们可以通过链接静态库来替换默认的 malloc。他们怎么能这么做呢?我想像这样实现我的自定义 malloc 函数。