我想编写一个低级日志记录function,如下所示:
DO_DBG("some string", val1, val2)
我想要它做的是,出于性能原因,将指针存储到字符串而不是字符串的副本。 这假定该字符串是只读文字。 为了防止人们不得不调试调试器,如果DO_DBG
的第一个参数是在代码与文本等的可写部分中,那么编译器会抱怨会很好。我想知道是否存在这样做的机制。 (我正在使用gcc 4.9.1,ld 2.24)。
您可以使用自动文字字符串连接来获得优势:
#define DO_DBG(s, a, b) _DO_DBG("" s, a, b)
并将您的真实宏实现为_DO_DBG
。
您可以设置SIGSEGV
处理程序,然后尝试执行以下操作:
s[0] = s[0];
如果处理程序被触发,则意味着该变量位于只读段中,因此您可以保存指针。 如果没有,您可以投诉(或只是复制字符串)。
您需要声明字符串volatile
以便编译器不会优化分配。
或者,您可以使用stringify宏构造:
#define DO_DBG(s, a, b) DO_DBG_INTERNAL(# s, a, b)
并调用你的函数DO_DGB_INTERNAL
所以人们会这样做:
DO_DBG(some string, val1, val2)
PS,很可能是一个可变函数和宏在这里是个好主意。
您的函数获取指向字符串开头的指针。 如果您的操作系统允许它,并且编译器以这种方式设置它,则可以在只读存储器区域中分配常量字符串(如示例中所示)。 如果您的编译器是智能的,它将存储一个出现多次的字符串常量的副本。 它甚至可能会发现某些字符串从未被使用过,而根本就没有存储它们。
除了上述内容之外,除非您的程序依赖于未定义的行为(在常量字符串上写入),否则您应该无法确定它是否在只读内存中。 您可以比较字符串的地址,看它们是否只是一个副本,但就是这样。
在任何合理的 C实现中(也就是说,只是为了让你搞砸了),如果字符串是只读的,那么你将看不到(或者至多是极小的)性能差异,读写,一份或几份。
如果你用char *
参数编写函数,并将指针存储起来(不是复制到指向的字符串),你应该总是得到相同的字符串(除非你的环境真的很奇怪)。
这是一个基于SIGSEGV处理程序的测试,用于检查指向的内存是否以只读方式映射:
需要了解更多c/c++开发分享C测试变量是否在只读部分,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!
#define _GNU_SOURCE #include #include #include #include static sigjmp_buf label; static void segv_hndlr(int Sig) { siglongjmp(label,1); } //safe in this ctx _Bool is_ro(char volatile *X) { _Bool r=0; struct sigaction old; X[0]; //fault now if the target isn't writable if(sigsetjmp(label,1)) { r=1; goto out; } sigaction(SIGSEGV,&(struct sigaction){.sa_handler=segv_hndlr}, &old); X[0]=X[0]; out: sigaction(SIGSEGV,&old, NULL); return r; } //example: int main() { #define PR_BOOL(X) printf(#X"=%dn", X) char bar[]="bar"; char *baz = strdup("baz"); static int const static_ro_int = 42; int const auto_ro_int = 42; PR_BOOL(is_ro("foo")); //1 PR_BOOL(is_ro(bar)); //0 PR_BOOL(is_ro(baz)); //0 PR_BOOL(is_ro((void*)&static_ro_int)); //1 PR_BOOL(is_ro((void*)&auto_ro_int)); //0 }
以上就是c/c++开发分享C测试变量是否在只读部分相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/979041.html