編輯:使標題更清晰一些。包裝的功能僅在鏈接爲靜態鏈接庫時調用
我試圖用我自己的函數來包裝glibc的__assert_fail
和__assert_perror_fail
函數,它們使用syslog
來記錄消息。
我已經驗證,如果我失敗了一個斷言我的功能被調用。問題在於libzmq的斷言。當我使用-static
構建時,libzmq的斷言僅調用我的包裝函數。
注意
我修補libzmq打電話
__assert_*
而不是fprintf(stderr, ...)
,我已經驗證它正確調用__assert_*
。我也打補丁libzmq從zmq_assert宏中隨機地斷言失敗,以便我可以很容易地重現。如果補丁是想要的,我會放棄它。
下面是一些測試代碼
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <zmq.h>
extern "C" void
__wrap___assert_perror_fail(int __errnum, const char *__file,
unsigned int __line, const char *__function)
{
fprintf(stderr, "TESTING123:: %s:%u %s: Unexpected error: %s.\n",
__file, __line, __function, strerror(__errnum));
abort();
}
extern "C" void
__wrap___assert_fail(const char *__assertion, const char *__file,
unsigned int __line, const char *__function)
{
fprintf(stderr, "TESTING123:: %s:%u %s: Assertion '%s' failed.\n",
__file, __line, __function, __assertion);
abort();
}
int main()
{
#ifdef DO_ASSERT
assert(1 == 0);
#endif
void *ctx = zmq_init(0);
void *req = zmq_socket(ctx, ZMQ_REQ);
void *rep = zmq_socket(ctx, ZMQ_REQ);
zmq_bind(rep, "inproc://inproc-1");
zmq_connect(req, "inproc://inproc-1");
unsigned long long c = 0;
while (1) {
zmq_msg_t msg;
zmq_msg_init_size(&msg, 1024);
zmq_send(req, &msg, 0);
zmq_msg_close(&msg);
zmq_msg_init(&msg);
zmq_recv(rep, &msg, 0);
zmq_send(rep, &msg, 0);
zmq_msg_close(&msg);
zmq_msg_init(&msg);
zmq_recv(req, &msg, 0);
zmq_msg_close(&msg);
++c;
if (c % 1000000 == 0) {
fprintf(stderr, "processed %llu messages\n", c);
}
}
return 0;
}
我所要建造4點的方式有/無DO_ASSERT,動態/靜態
$ g++ -DDO_ASSERT -o t-me-dyn t.cc -Wl,-wrap,__assert_fail -Wl,-wrap,__asser_perror_fail -lzmq -lpthread -luuid -lrt
$ g++ -static -DDO_ASSERT -o t-me-sta t.cc -Wl,-wrap,__assert_fail -Wl,-wrap,__asser_perror_fail -lzmq -lpthread -luuid -lrt
$ g++ -o t-zmq-dyn t.cc -Wl,-wrap,__assert_fail -Wl,-wrap,__asser_perror_fail -lzmq -lpthread -luuid -lrt
$ g++ -static -o t-zmq-sta t.cc -Wl,-wrap,__assert_fail -Wl,-wrap,__asser_perror_fail -lzmq -lpthread -luuid -lrt
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../lib/libzmq.a(libzmq_la-ip.o): In function 'zmq::resolve_ip_interface(sockaddr_storage*, unsigned int*, char const*)':
(.text+0x49b): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
並運行他們
當我得到以下$ for bin in t-{me,zmq}-{dyn,sta}; do echo ==== $bin ====; ./$bin; done
==== t-me-dyn ====
TESTING123:: t.cc:29 int main(): Assertion '1 == 0' failed.
Aborted
==== t-me-sta ====
TESTING123:: t.cc:29 int main(): Assertion '1 == 0' failed.
Aborted
==== t-zmq-dyn ====
t-zmq-dyn: lb.cpp:142: int zmq::lb_t::send(zmq_msg_t*, int): Assertion 'rc == 0' failed.
Aborted
==== t-zmq-sta ====
TESTING123:: lb.cpp:142 int zmq::lb_t::send(zmq_msg_t*, int): Assertion 'rc == 0' failed.
Aborted
那麼我做錯了什麼?據man ld
如果您使用的malloc --wrap該文件鏈接其他代碼,然後將所有來電「的malloc」將調用函數「--wrap malloc中調用」代替。
這不是我所看到的。
我在想,我的' - wrap'這個想法就像你說的那樣錯了。在試圖定義我自己的'__assert_fail'後,我來找到'--wrap',但那不起作用。我會再次嘗試驗證。我終於可以使用'__attribute __((別名(「my_assert_fail」))' – mmlb
所以我回去測試了這裏發佈的示例代碼,以及我的應用程序,並且它們都在我定義'__assert_fail'和'__assert_perror_fail'時工作。 !我想知道爲什麼我認爲它不起作用......無論如何@Employed感謝您的答案。 – mmlb