单元测试涉及失败的代码路径的最佳方法是什么malloc()?在大多数情况下,它可能并不重要,因为你正在做类似的事情
thingy *my_thingy = malloc(sizeof(thingy));
if (my_thingy == NULL) {
fprintf(stderr, "We're so screwed!\n");
exit(EXIT_FAILURE);
}
Run Code Online (Sandbox Code Playgroud)
但在某些情况下,除了死亡之外你还有其他选择,因为你已经为缓存或其他任何东西分配了一些额外的东西,你可以收回那些记忆.
但是,在那些您可以尝试从失败malloc()中恢复的情况下,您在代码路径中执行的操作非常棘手并且容易出错,这使得测试变得尤为重要.你是怎么做到这一点的?
我一直在寻找glibc的一些源代码,特别是nptl代码,我发现它有点难以理解,因为它似乎有我不熟悉的约定.
例如,我正在查看一个非常小的文件pthread_equal.c,我有一些问题:
22 int
23 __pthread_equal (thread1, thread2)
24 pthread_t thread1;
25 pthread_t thread2;
26 {
27 return thread1 == thread2;
28 }
29 strong_alias (__pthread_equal, pthread_equal)
Run Code Online (Sandbox Code Playgroud)
第22和23行的声明看起来像我理解的东西.它的返回类型是int函数名__pthread_equal和参数列表(thread1, thread2).但第24 pthread_t thread1;和25 行的声明pthread_t thread2;是什么?看起来这些被声明为全局变量,但我不明白其目的.我在nptl目录中的许多文件中都看到过这种模式,并且无法弄清楚为什么会这样做.
什么是strong_alias?快速谷歌搜索有使用这个的例子,但我没有找到任何文档的链接.
什么是用作序两个下划线一些名字的原因__,有些用一个下划线_.我见过的大多数代码使用了两个下划线,但我想我已经看到了一些使用下划线的地方.例如在pthreadP.h中
556 /* Old cleanup interfaces, still used in libc.so. */
557 extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
558 void (*routine) (void *), void *arg);
559 extern void …Run Code Online (Sandbox Code Playgroud)我开始研究glibc(GNU Libc)以了解它是如何编写的.在malloc.c,我发现了一段代码如下:
#ifndef void
#define void void
#endif
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释这意味着什么?不void总是定义?
谢谢
假设我曾经习惯ptr = malloc(old_size);用old_size字节分配内存块.只有第一个header_size字节才有意义.我要把尺寸增加到new_size.
new_size大于old_size且old_size大于header_size.
之前:
/- - - - - - - old_size - - - - - - - \
+===============+---------------------+
\-header_size-/
Run Code Online (Sandbox Code Playgroud)
后:
/- - - - - - - - - - - - - - - new_size - - - - - - - - - - - - - - - - - - -\
+===============+------------------------------------------------------------+
\- header_size-/
Run Code Online (Sandbox Code Playgroud)
我不关心之后存储的内容,ptr + …
我在我的Linux Mint 14 Nadia中安装了Matlab(uname -a显示:Linux Ideapad-Z570 3.5.0-17-generic#28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux)当从命令行调用它时,我会得到:"/ lib64/libc.so not found".
我通过在/ lib64中创建链接来遵循mathworks的帮助:
ln -s /lib/x86_64-linux-gnu/libc.so.6 .
Run Code Online (Sandbox Code Playgroud)
这解决了这个问题.
现在,如果我找到这个库,我得到:
locate "libc.so"
/lib/i386-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libc.so.6
/usr/lib/x86_64-linux-gnu/libc.so
Run Code Online (Sandbox Code Playgroud)
我将在这台计算机上使用gcc进行编译,我希望能有完整的64位编译.拥有所有这些不同的libc.so库到底意味着什么?gnu编译器将使用哪一个?我需要做什么不同的gcc编译64位?
我也想尽可能地为我的新i7核心进行优化!
我-lrt将最后一个链接器标志作为编译器.但仍然得到这个错误.
arif@khost:~/sak/sak.exosip$ gcc eXo_init.c -I/opt/osip2/include -I/opt/exosip/include -L/opt/osip2/lib -L/opt/exosip/lib -leXosip2 -losipparser2 -losip2 -lrt
/opt/osip2/lib/libosip2.so: undefined reference to `clock_gettime'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
手册页说:
NAME
clock_getres, clock_gettime, clock_settime - clock and time functions
SYNOPSIS
#include <time.h>
int clock_getres(clockid_t clk_id, struct timespec *res);
int clock_gettime(clockid_t clk_id, struct timespec *tp);
int clock_settime(clockid_t clk_id, const struct timespec *tp);
Link with -lrt.
Run Code Online (Sandbox Code Playgroud)
所以我有点困惑,我做错了.
我试图在librt.so没有运气的情况下阅读符号:
arif@khost:~/sak/ortp/src/tests$ nm /lib/x86_64-linux-gnu/librt-2.15.so
nm: /lib/x86_64-linux-gnu/librt-2.15.so: no symbols
Run Code Online (Sandbox Code Playgroud)
更新1我无法读取符号的原因librt.so是它们被"剥离".我在哪里可以获得符号名称?
arif@khost:~/sak/ortp/src/tests$ file /lib/x86_64-linux-gnu/librt-2.15.so
/lib/x86_64-linux-gnu/librt-2.15.so: ELF …Run Code Online (Sandbox Code Playgroud) 我在程序中的某个点上进行了堆栈跟踪.一旦与libc中的backtrace_symbols()功能,一旦与unw_get_proc_name()来自libunwind.
backtrace_symbols()输出:
/home/jj/test/mylib.so(+0x97004)[0x7f6b47ce9004]
Run Code Online (Sandbox Code Playgroud)
unw_get_proc_name()输出:
ip: 0x7f6b47ce9004, offset: 0x458e4
Run Code Online (Sandbox Code Playgroud)
在这里,您可以看到指令指针地址(0x7f6b47ce9004)是相同且正确的.功能失调0x97004来自backtrace_symbols()也是正确的,但没有一个我从拿到unw_get_proc_name() (0x458e4).
有人知道这里发生了什么以及可能导致这种抵消差异的原因是什么?
两种方法都使用类似的代码,如下面的示例:
回溯():
void *array[10];
size_t size;
size = backtrace(array, 10);
backtrace_symbols_fd(array, size, STDERR_FILENO);
Run Code Online (Sandbox Code Playgroud)
libunwind:
unw_cursor_t cursor;
unw_context_t context;
unw_getcontext(&context);
unw_init_local(&cursor, &context);
while (unw_step(&cursor) > 0) {
unw_word_t offset, pc;
char fname[64];
unw_get_reg(&cursor, UNW_REG_IP, &pc);
fname[0] = '\0';
(void) unw_get_proc_name(&cursor, fname, sizeof(fname), &offset);
printf ("%p : (%s+0x%x) [%p]\n", pc, fname, offset, …Run Code Online (Sandbox Code Playgroud) 当您调用clock_gettime()它时,返回timespec结构.
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
Run Code Online (Sandbox Code Playgroud)
我没有在手册页中找到tv_nsec不会超过一秒的保证.实际存在保证吗?它可能依赖于linux的库(glibc?)实现吗?
关键的想法是:我是否需要"规范化"来自clock_gettime()函数的任何结果?
我正在研究如何在Linux系统上实现TLS(线程本地存储).文档ELF处理线程局部存储解释了程序对线程局部变量的要求如何在ELF二进制文件中编码,以及"运行时"如何处理这些二进制文件.
但是,我不清楚在实践中,设置TLS区域的"运行时"是Linux内核(及其加载ELF二进制文件的代码)还是libc中的一些初始化代码.有人能简单解释一下吗
(背景:我正在尝试静态链接并运行一个应用程序,但它在启动时会出现段错误.在gdb中,我可以看到segfaulting代码是来自libc的一些初始化代码.它试图使用相对于的地址读取静态变量GS,但GS为零.)
我试图捕获libc检测到错误条件时生成的错误消息.例如,我的测试代码:
#include <stdlib.h>
int main()
{
char* p = (char*)malloc(10);
free(p);
free(p);
}
Run Code Online (Sandbox Code Playgroud)
生成此输出
$ ./main
*** Error in `./main': double free or corruption (fasttop): 0x000000000124b010 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7d1fd)[0x7f8c121291fd]
./main[0x400b86]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f8c120cdaf5]
./main[0x400a79]
... <snip>
Run Code Online (Sandbox Code Playgroud)
但是,它不是写入stderr或stdout,而是/ dev/tty(我发现使用strace)
open("/dev/tty", O_RDWR|O_NOCTTY|O_NONBLOCK) = 3
writev(3, [{"*** Error in `", 14}, {"./main", 6}, {"': ", 3}, {"double free or corruption (fastt"..., 35}, {": 0x", 4}, {"00000000011bf010", 16}, {" ***\n", 5}], 7*** Error in `./main': double free or corruption (fasttop): 0x00000000011bf010 ***
) = …Run Code Online (Sandbox Code Playgroud)