मैं सी में अपने प्रोग्राम का मेमोरी लेआउट देखना चाहता हूं ताकि मैं रन-टाइम के दौरान मेमोरी के सभी अलग-अलग हिस्सों को समझ सकूं जैसे कि बीएसएस या हेप में बदलाव के लिए?रन-टाइम के दौरान सी में मेरे प्रोग्राम के मेमोरी लेआउट को कैसे देखें?
उत्तर
लिनक्स में, प्रक्रिया पीआईडी के लिए, /proc/PID/maps
और /proc/PID/smaps
छद्म जीवों को देखें। (प्रक्रिया ही /proc/self/maps
और /proc/self/smaps
उपयोग कर सकते हैं।)
उनकी सामग्री man 5 proc में दर्ज कर रहे हैं।
यहां एक उदाहरण दिया गया है कि आप पता श्रेणी संरचनाओं की एक लिंक की गई सूची में सामग्री को कैसे पढ़ सकते हैं।
मेम-stats.h:
#ifndef MEM_STATS_H
#define MEM_STATS_H
#include <stdlib.h>
#include <sys/types.h>
#define PERMS_READ 1U
#define PERMS_WRITE 2U
#define PERMS_EXEC 4U
#define PERMS_SHARED 8U
#define PERMS_PRIVATE 16U
typedef struct address_range address_range;
struct address_range {
struct address_range *next;
void *start;
size_t length;
unsigned long offset;
dev_t device;
ino_t inode;
unsigned char perms;
char name[];
};
address_range *mem_stats(pid_t);
void free_mem_stats(address_range *);
#endif /* MEM_STATS_H */
मेम-stats.c:
#define _POSIX_C_SOURCE 200809L
#define _BSD_SOURCE
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "mem-stats.h"
void free_mem_stats(address_range *list)
{
while (list) {
address_range *curr = list;
list = list->next;
curr->next = NULL;
curr->length = 0;
curr->perms = 0U;
curr->name[0] = '\0';
free(curr);
}
}
address_range *mem_stats(pid_t pid)
{
address_range *list = NULL;
char *line = NULL;
size_t size = 0;
FILE *maps;
if (pid > 0) {
char namebuf[128];
int namelen;
namelen = snprintf(namebuf, sizeof namebuf, "/proc/%ld/maps", (long)pid);
if (namelen < 12) {
errno = EINVAL;
return NULL;
}
maps = fopen(namebuf, "r");
} else
maps = fopen("/proc/self/maps", "r");
if (!maps)
return NULL;
while (getline(&line, &size, maps) > 0) {
address_range *curr;
char perms[8];
unsigned int devmajor, devminor;
unsigned long addr_start, addr_end, offset, inode;
int name_start = 0;
int name_end = 0;
if (sscanf(line, "%lx-%lx %7s %lx %u:%u %lu %n%*[^\n]%n",
&addr_start, &addr_end, perms, &offset,
&devmajor, &devminor, &inode,
&name_start, &name_end) < 7) {
fclose(maps);
free(line);
free_mem_stats(list);
errno = EIO;
return NULL;
}
if (name_end <= name_start)
name_start = name_end = 0;
curr = malloc(sizeof (address_range) + (size_t)(name_end - name_start) + 1);
if (!curr) {
fclose(maps);
free(line);
free_mem_stats(list);
errno = ENOMEM;
return NULL;
}
if (name_end > name_start)
memcpy(curr->name, line + name_start, name_end - name_start);
curr->name[name_end - name_start] = '\0';
curr->start = (void *)addr_start;
curr->length = addr_end - addr_start;
curr->offset = offset;
curr->device = makedev(devmajor, devminor);
curr->inode = (ino_t)inode;
curr->perms = 0U;
if (strchr(perms, 'r'))
curr->perms |= PERMS_READ;
if (strchr(perms, 'w'))
curr->perms |= PERMS_WRITE;
if (strchr(perms, 'x'))
curr->perms |= PERMS_EXEC;
if (strchr(perms, 's'))
curr->perms |= PERMS_SHARED;
if (strchr(perms, 'p'))
curr->perms |= PERMS_PRIVATE;
curr->next = list;
list = curr;
}
free(line);
if (!feof(maps) || ferror(maps)) {
fclose(maps);
free_mem_stats(list);
errno = EIO;
return NULL;
}
if (fclose(maps)) {
free_mem_stats(list);
errno = EIO;
return NULL;
}
errno = 0;
return list;
}
एक उदाहरण कार्यक्रम ऊपर का उपयोग करने, example.c:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "mem-stats.h"
int main(int argc, char *argv[])
{
int arg, pid;
char dummy;
if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s PID\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "You can use PID 0 as an alias for the command itself.\n");
fprintf(stderr, "\n");
return EXIT_SUCCESS;
}
for (arg = 1; arg < argc; arg++)
if (sscanf(argv[arg], " %i %c", &pid, &dummy) == 1) {
address_range *list, *curr;
if (!pid)
pid = getpid();
list = mem_stats((pid_t)pid);
if (!list) {
fprintf(stderr, "Cannot obtain memory usage of process %d: %s.\n", pid, strerror(errno));
return EXIT_FAILURE;
}
printf("Process %d:\n", pid);
for (curr = list; curr != NULL; curr = curr->next)
printf("\t%p .. %p: %s\n", curr->start, (void *)((char *)curr->start + curr->length), curr->name);
printf("\n");
fflush(stdout);
free_mem_stats(list);
} else {
fprintf(stderr, "%s: Invalid PID.\n", argv[arg]);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
और एक Makefile यह आसान बनाने के लिए निर्माण:
CC := gcc
CFLAGS := -Wall -Wextra -O2 -fomit-frame-pointer
LDFLAGS :=
PROGS := example
.PHONY: all clean
all: clean $(PROGS)
clean:
rm -f *.o $(PROGS)
%.o: %.c
$(CC) $(CFLAGS) -c $^
example: mem-stats.o example.o
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o [email protected]
ध्यान दें कि चाहिए उपयोग टैब वर्ण, नहीं रिक्त स्थान ऊपर Makefile में तीन दांतेदार लाइनों। ऐसा लगता है कि संपादक यहां रिक्त स्थान के लिए टैब बदल देता है, ताकि आप
sed -e 's|^ *|\t|' -i Makefile
का उपयोग कर आप खरोज ठीक नहीं है, और एक Makefile में रिक्तियों का उपयोग करके कि ठीक करने के लिए, उदाहरण के लिए, आप एक देखेंगे की जरूरत है *** missing separator. Stop
के समान त्रुटि संदेश।
कुछ एडिटर स्वचालित रूप से रिक्त स्थान की एक संख्या में एक टैब कुंजी दबाने कनवर्ट करते हैं, तो आप जो कुछ भी संपादक आप उपयोग के संपादक सेटिंग्स में तल्लीन करना पड़ सकता है। अक्सर, संपादक चिपकाए गए टैब वर्ण को बरकरार रखते हैं, ताकि आप हमेशा किसी अन्य प्रोग्राम से टैब पेस्ट करने का प्रयास कर सकें।
संकलन करने के लिए और चलाने के लिए, ऊपर फ़ाइलों को सहेजने और
make
./example 0
चलाने उदाहरण कार्यक्रम में ही द्वारा प्रयुक्त स्मृति पर्वतमाला मुद्रित करने के लिए। आप देखना चाहते हैं, तो आपके पल्सऑडियो डेमॉन द्वारा प्रयुक्त स्मृति पर्वतमाला, चलाने
./example $(ps -o pid= -C pulseaudio)
ध्यान दें कि मानक पहुंच प्रतिबंध लागू होते हैं, का कहना है। एक सामान्य उपयोगकर्ता केवल उस उपयोगकर्ता के रूप में चलने वाली प्रक्रियाओं की स्मृति श्रृंखला देख सकता है; अन्यथा आपको सुपरसुर विशेषाधिकारों की आवश्यकता है (sudo
या इसी तरह)।
यदि आप लिनक्स पर स्थिर कोर डंप प्राप्त करने के लिए गोरकोर का उपयोग करते हैं, तो यह gdb का हिस्सा है ...
gcore $pid > Corefile
या
gcore -o core_dump $pid
डिबग करने के लिए चल रहे एक कार्यक्रम gdb
gdb -p 1234
का उपयोग कर तो यह में चारों ओर से प्रहार इसे करने के लिए देते हैं। यह देखने के लिए कि यह कैसे बाहर
(gdb) maint info sections
Exec file:
`/home/foo/program', file type elf32-i386.
[0] 0x8048134->0x8048147 at 0x00000134: .interp ALLOC LOAD READONLY DATA HAS_CONTENTS
[1] 0x8048148->0x8048168 at 0x00000148: .note.ABI-tag ALLOC LOAD READONLY DATA HAS_CONTENTS
[2] 0x8048168->0x804818c at 0x00000168: .note.gnu.build-id ALLOC LOAD
.....
.....
[23] 0x8049a40->0x8049ad1 at 0x00000a40: .data ALLOC LOAD DATA HAS_CONTENTS
[24] 0x8049ad1->0x8049ad4 at 0x00000ad1: .bss ALLOC
रखी है रजिस्टरों में चारों ओर से प्रहार करने के लिए उपयोग करें
(gdb) info all-registers
eax 0xfffffdfc -516
ecx 0x0 0
edx 0x1 1
ebx 0xffeedc28 -1123288
esp 0xffeedc0c 0xffeedc0c
ebp 0xffeedc78 0xffeedc78
esi 0x1308 4872
edi 0x45cf 17871
.... snipped
आप एक विशेष समारोह उपयोग disassemble
के लिए इस्तेमाल किया विधानसभा देखना चाहते हैं। इसका उपयोग स्मृति में पते के साथ भी किया जा सकता है।
pmap [ -x | -d ] [ -q ] pids...
pmap -V
pmap procps संग्रह का हिस्सा है:
(gdb) disassemble main
Dump of assembler code for function main:
0x080483f0 <+0>: lea 0x4(%esp),%ecx
0x080483f4 <+4>: and $0xfffffff0,%esp
0x080483f7 <+7>: mov $0x8048780,%edx
0x080483fc <+12>: pushl -0x4(%ecx)
0x080483ff <+15>: push %ebp
0x08048400 <+16>: mov %esp,%ebp
....
....
एक अन्य विकल्प pmap उपकरण है जो इस प्रक्रिया स्मृति मानचित्रण विवरण उदासीनता है।
यदि आप भौतिक मानचित्रण में रुचि रखते हैं, तो आप पेजमैप पर एक नज़र डाल सकते हैं, जिसे हाल ही में लिनक्स कर्नेल में उपलब्ध कराया गया है ताकि प्रक्रिया को इसकी भौतिक स्मृति जानकारी पता चल सके। यह उपयोगकर्ता अंतरिक्ष चालक विकास के लिए उपयोगी हो सकता है जहां उपयोगकर्ता अंतरिक्ष प्रक्रिया को बफर के भौतिक पते को डीएमए गंतव्य के रूप में ढूंढने की आवश्यकता होती है।
- 1. लिनक्स में प्रोग्राम मेमोरी लेआउट
- 2. सी/सी ++ प्रोग्राम का मेमोरी लेआउट कैसा है?
- 3. मेमोरी लेआउट सी ++ ऑब्जेक्ट्स
- 4. सी प्रोग्राम के मेमोरी उपयोग को कैसे प्रोफाइल करें
- 5. सी # सीएफ: मेरे प्रोग्राम
- 6. मेरे सी ++ प्रोग्राम
- 7. पावरपॉइंट में प्रोग्राम लेआउट को स्लाइड लेआउट कैसे बदलें?
- 8. संकलन के दौरान प्रोग्राम कैसे लिखें?
- 9. मेरे सी # प्रोग्राम
- 10. सी ++ नया ऑपरेटर - मेमोरी लेआउट
- 11. जीडीबी में मेमोरी रेंज देखें?
- 12. रनटाइम के दौरान साझा लाइब्रेरी के अंदर डिबगिंग/ट्रेसिंग?
- 13. देखें व्यू (लेआउट)
- 14. सी # रनटाइम के दौरान सभी चर और वर्तमान मानों को कैसे डंप करें
- 15. रनटाइम के दौरान लेबल बाधाओं को कैसे बदला जाए?
- 16. जेएमटर में रनटाइम के दौरान परिणाम फ़ाइल नाम कैसे बदलें?
- 17. लेआउट परेशानियों के बिना रनटाइम पर भाषा को कैसे बदलें
- 18. सामान्य प्रोग्राम के निष्पादन के दौरान एफ #
- 19. प्रोग्राम लेआउट को हटाएं
- 20. रनटाइम के दौरान अभिविन्यास को कैसे लॉक करें
- 21. रनटाइम के दौरान उपलब्ध टेक्स्टफ़िल्ड्स की एक सूची प्राप्त करें?
- 22. रनटाइम पर सी में चर के प्रकार को कैसे जांचें?
- 23. एक सी या सी ++ प्रोग्राम को मेमोरी और सीपीयू चक्र भराव के रूप में कार्य करने के लिए कैसे लिखें?
- 24. इस प्रोग्राम को मेरे सी # एप्लिकेशन
- 25. मेरे प्रोग्राम
- 26. रनटाइम संकलन के दौरान संदिग्ध संदर्भ त्रुटि
- 27. जावा प्रोग्राम के मेमोरी खपत के मुद्दे
- 28. विंडोज़ प्रोग्राम मेरे डीएलएल के मैप्स से पहले मेमोरी क्षेत्रों को कैसे आरक्षित कर सकता हूं?
- 29. नेट कचरा कलेक्टर - देखें कि रनटाइम
- 30. मेरे प्रोग्राम को पृष्ठभूमि प्रक्रिया कैसे बनाएं
किसी भी विशेष मंच पर? – isedev
@isedev: मुख्य रूप से लिनक्स –
@ सुर्याप्रकाशपेटेल जीडीबी पर एक नज़र डालें। या अगर आप कुछ दृश्य चाहते हैं तो इडा का उपयोग करें। – fuz