对于gcc项目,__FUNCTION__
,__FILE__
和__func__
返回的指针是否保证指向持久内存? (也就是说,我可以安全地推断另一个函数范围内的指针吗?)我知道__func__
应该在函数的开头表现为const char __func__ = "filename"
,这意味着&#34 ;文件名"指向程序数据段中的某些内容,因此指针应该在函数外部有效。其他的是字符串,它们应该再次在数据部分创建条目。话虽这么说,我不相信它,我想知道这里是否有人可以确认这个假设是否正确。
例如:
struct debugLog_t {
const char * func;
const char * file;
const char * function;
uint32_t line;
int val;
} log;
struct debugLog_t someLog = {};
someFunc() {
// create debug log:
if (x) {
//uh oh...
someLog.func = __func__;
someLog.function = __FUNCTION__;
someLog.file = __FILE__;
someLog.line = line;
someLog.val = val;
}
}
void dumpSomeLog() {
printf("%s(%s) -- %s.%d: error val is x\n",
someLog.function, someLog.func, someLog.file, someLog.line,
someLog.val);
}
我想这样做是为了减少录制调试日志的内存/处理时间。
答案 0 :(得分:1)
我不会将持久性内存称为persistence上的wikipage),而是只读code segment中的内存(或部分)。
是的,__func__
,__FUNCTION__
,__FILE__
去那里(如static const char[]
数组);像文字字符串一样。
请注意,两次出现的文字字符串(如"ab"
)可能会或者不会被编译到相同的地址中(同样,"bc"
可以或不等于指针"abc"+1
)。同样,两次出现__FILE__
;但是,在相同的函数中,__func__
的所有出现都应该具有相同的地址。
使用GCC(至少在-O1
优化时)相同内容的文字常量字符串共享相同的位置。我甚至认为,在功能foo
中,__func__
和"foo"
可能共享相同的地址(但即使在-O2
,他们也不会共享GCC)。您可以通过使用gcc -fverbose-asm -S -O1
进行编译来查看,并查看生成的*.s
汇编程序文件。
例如:
const char*f(int x) {
if (x==0) return "f";
if (x>0) return __func__;
return __FUNCTION__;
}
使用gcc -O -fverbose-asm -S
编译(在Linux / Debian / Sid / x86-64上使用GCC 7)
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "f"
.text
.globl f
.type f, @function
f:
.LFB0:
.cfi_startproc
# f.c:2: if (x==0) return "f";
leaq .LC0(%rip), %rax #, <retval>
testl %edi, %edi # x
je .L1 #,
# f.c:3: if (x>0) return __func__;
testl %edi, %edi # x
# f.c:4: return __FUNCTION__;
leaq __func__.1795(%rip), %rax #, tmp94
leaq __FUNCTION__.1796(%rip), %rdx #, tmp95
cmovle %rdx, %rax # tmp94,, tmp95, <retval>
.L1:
# f.c:5: }
rep ret
.cfi_endproc
.LFE0:
.size f, .-f
.section .rodata
.type __FUNCTION__.1796, @object
.size __FUNCTION__.1796, 2
__FUNCTION__.1796:
.string "f"
.type __func__.1795, @object
.size __func__.1795, 2
__func__.1795:
.string "f"
.ident "GCC: (Debian 7.2.0-8) 7.2.0"
即使使用-Os
或-O3
,我在代码段中也会获得三个不同的位置。
然而Clang 5与-O3
(或甚至-O1
)将所有三个"f"
,__FUNCTION__
和__func__
合并在一起相同的位置(并通过删除它来优化测试):
.type f,@function
f: # @f
.cfi_startproc
# BB#0:
movl $.L.str, %eax
retq
.Lfunc_end0:
.size f, .Lfunc_end0-f
.cfi_endproc
# -- End function
.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "f"
.size .L.str, 2
因此,您关注的指针是代码段中static const char[]
的指针,但您不应总是期望__func__
具有与__FUNCTION__
相同的地址(即使可能)
答案 1 :(得分:1)
是的。这些常量实际上就像static
声明一样。从GCC docs开始,__func__
就像函数以
static const char __func__[] = "function-name";
和__FUNCTION__
基本相同。
答案 2 :(得分:1)
根据C2011,public ActionResult NewCountry(string button,string Country,string Notes)
{
switch (button)
{
case "Save":
bool exists = InsertCountry(Country, Notes);
if (exists)
{
return Redirect("/Maintenance/Maintenance/Country?alert=true");
}
else
return Redirect("/Maintenance/Maintenance/Country");
case "Cancel":
//Need to redirect to the countries page.
return Redirect("/Maintenance/Maintenance/Country");
}
return View();
}
宏扩展为
当前源文件的假定名称( 字符串文字 )。
(C2011 6.10.8.1/1;重点补充)
因此,是的,您可以将其分配给指针变量,并期望能够在程序的生命周期内安全地取消引用它。
该标准还指定了__FILE__
的表单,它实际上是一个隐式的变量,而不是宏:
标识符
__func__
应由隐式声明 翻译好像,紧跟着每个人的开口支撑 函数定义,声明__func__
出现了[...]。
在这种情况下,标识符指定具有静态存储持续时间的static const char __func__[] = "function-name";
数组。在这种情况下,也可以安全地记录指向此的指针,并在程序运行后的任意时间取消引用。
作为扩展和向后兼容性规定,GCC还提供const char
作为__FUNCTION__
的别名,因此相同的答案适用于前者适用于后者:是的,它们引用的字符串驻留在持久性内存中,您可以从另一个函数安全地访问它。