如何在Linux下確定線程堆棧的大小及其大小?有沒有可用的C/C++ API或在gdb中查找的方法? 感謝確定線程的堆棧大小和位置
回答
這裏是這樣,涉及到閱讀/proc/self/maps
的不同方法。與其他一些方法不同,它不需要在程序開始時使用特殊的儀器,並且可以爲堆棧的末尾提供精確的位置。
如果您嘗試cat /proc/self/maps
,你得到的東西是這樣的:
00400000-0040c000 r-xp 00000000 08:01 6039736 /usr/bin/cat
0060b000-0060c000 r--p 0000b000 08:01 6039736 /usr/bin/cat
0060c000-0060d000 rw-p 0000c000 08:01 6039736 /usr/bin/cat
00908000-00929000 rw-p 00000000 00:00 0 [heap]
7fcdb1c68000-7fcdb1e01000 r-xp 00000000 08:01 6032628 /usr/lib/libc-2.21.so
7fcdb1e01000-7fcdb2000000 ---p 00199000 08:01 6032628 /usr/lib/libc-2.21.so
7fcdb2000000-7fcdb2004000 r--p 00198000 08:01 6032628 /usr/lib/libc-2.21.so
7fcdb2004000-7fcdb2006000 rw-p 0019c000 08:01 6032628 /usr/lib/libc-2.21.so
7fcdb2006000-7fcdb200a000 rw-p 00000000 00:00 0
7fcdb200a000-7fcdb202c000 r-xp 00000000 08:01 6032717 /usr/lib/ld-2.21.so
7fcdb21f5000-7fcdb21f8000 rw-p 00000000 00:00 0
7fcdb2209000-7fcdb222b000 rw-p 00000000 00:00 0
7fcdb222b000-7fcdb222c000 r--p 00021000 08:01 6032717 /usr/lib/ld-2.21.so
7fcdb222c000-7fcdb222d000 rw-p 00022000 08:01 6032717 /usr/lib/ld-2.21.so
7fcdb222d000-7fcdb222e000 rw-p 00000000 00:00 0
7ffe78c41000-7ffe78c62000 rw-p 00000000 00:00 0 [stack]
7ffe78dba000-7ffe78dbc000 r--p 00000000 00:00 0 [vvar]
7ffe78dbc000-7ffe78dbe000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
正如你可以看到,有一個[stack]
條目。這可能是你正在尋找的。
一個例子程序來解析該行指出:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[]) {
FILE *file = fopen("/proc/self/maps", "r");
char line[1024];
void *result = NULL;
while (!feof(file)) {
if (fgets(line, sizeof(line)/sizeof(char), file) == NULL) {
break;
}
unsigned long start, end, offset;
unsigned int devma, devmi, ino;
char perms[6];
char path[128];
if (sscanf(line, "%lx-%lx %5s %lx %d:%d %d %127s", &start, &end, &perms, &offset, &devma, &devmi, &ino, &path) != 8) {
continue; // could not parse. fail gracefully and try again on the next line.
}
if (strcmp(path, "[stack]") == 0) { // use [stack:TID] for a thread besides the main thread
printf("Stack found from %lx to %lx\n", start, end);
break;
}
}
fclose(file);
return 0;
}
這將打印出類似這樣:
Stack found from 7fff91834000 to 7fff91855000
這可能是相當接近你在找什麼。
這就是我最終做到的。如果您有多個線程並且需要爲特定線程查找堆棧,則可以使用任何堆棧變量的地址並將其與堆棧範圍進行匹配。 – hlitz 2015-06-14 17:40:56
是的 - 你也可以使用'gettid()'和'[stack:TID]'。 – 2015-06-14 18:26:20
如果您能夠接受沒有得到確切的堆棧頂部(這可能足夠了我的應用程序),遍歷幀指針可以工作:
// main.c
#include <stdint.h>
// -fno-omit-frame-pointer might be required - otherwise you might get a crash
// might not be exactly at the top; but probably very close
void *stack_top() {
void **top;
asm("movq %%rbp, %0" : "=r" (top)); // set top to %rbp - replace with %ebp for 32-bit x86
// if top is higher in memory than the variable, then still part of the stack.
while ((uintptr_t) *top > (uintptr_t) &top) {
top = *top;
}
return top;
}
此操作,因爲在32位的%rbp
寄存器(或%ebp
寄存器)被用於將指針存儲到父堆棧幀的基(其中保存%rbp
或%ebp
值是) - 所以我們可以迭代遍歷這個鏈表直到我們到達一個無效的地址。
注意stack_top
可能在涉及&top
比較某些情況下失敗 - 我的系統端接一個指針,指向程序加載代碼的位置的鏈表,所以這是我發現,以檢測它的最好方法 - 但你會想要徹底地測試它。 (如果任何人有一個更好的辦法來檢測鏈的末端,請添加評論。)
實例測試程序:
#include <stdio.h>
#include <pthread.h>
void *test_another_layer(int x) {
return stack_top();
}
void *subthread(void *ptr) {
void *st1 = stack_top();
void *st2 = test_another_layer(0);
void *st3 = &ptr;
printf("stack tops 2: %x %x %x\n", st1, st2, st3);
return NULL;
}
int main(int argc, char *argv[]) {
void *st1 = stack_top();
void *st2 = test_another_layer(0);
void *st3 = &argc;
printf("stack tops: %x %x %x\n", st1, st2, st3);
pthread_t ot;
if (pthread_create(&ot, NULL, subthread, NULL) != 0) {
perror("cannot create");
return 1;
}
if (pthread_join(ot, NULL) != 0) {
perror("cannot join");
return 2;
}
return 0;
}
- 1. 配置boost ::線程堆棧大小
- 2. 最大線程堆棧大小.NET?
- 3. 如何確定最佳線程堆棧大小?
- 4. 誰負責確定堆棧的大小
- 5. 安全線程堆棧大小?
- 6. 估計線程堆棧大小
- 7. Keil RTX RTOS線程堆棧大小
- 8. 確定堆棧頂部的位置
- 9. 如何確定內核堆棧大小
- 10. 堆大小和位置
- 11. 線程共享堆棧位置?
- 12. 線程堆和堆棧
- 13. 如何設置主線程的堆棧大小
- 14. 使用QtConcurrent設置線程運行的堆棧大小
- 15. 固定大小堆棧Java
- 16. 通過線程例程多個變量和堆棧大小
- 17. 線程堆棧大小不匹配本機內存跟蹤線程堆棧大小
- 18. OutOfMemoryException,堆棧大小很大,大量的線程
- 19. 未設置線程堆棧大小;安裝彈性搜索
- 20. 無法在mysql中設置線程堆棧大小
- 21. 堆棧= java.lang.StackOverflowError的:堆棧大小8MB
- 22. 是否可以在Windows中決定線程的堆棧位置?
- 23. 在pthreads中指定線程堆棧大小
- 24. 爲什麼要減小Java JVM線程堆棧的大小?
- 25. 爲將來的QThreadPool線程和/或pthread_create調用設置默認堆棧大小
- 26. Pthreads:主線程和子線程堆棧大小之間的關係
- 27. 確定其中最大的調用堆棧大小被超過
- 28. Xss爲1個線程設置線程堆棧大小,對於所有線程的堆棧大小有什麼限制
- 29. Linux堆棧大小
- 30. Android堆棧大小
什麼語言? C/C++?還有別的嗎? – Mysticial 2013-03-20 05:01:28
使用第0幀來獲得最內層的框架,然後上來和上? – StarPinkER 2013-03-20 05:12:02
爲什麼你想通過API找到?做什麼的?你可以在TLS或全局數據中存儲每個線程中一些起始局部變量的地址... – 2013-03-20 06:21:59