c语言查看exe运行内存,c++ 运行时如何在C中查看我的程序的内存布局?

在Linux中,对于进程PID,请查看/ proc / PID / maps和/ proc / PID / smaps伪引用. (进程本身可以使用/ proc / self / maps和/ proc / self / smaps.)

以下是一个示例,说明如何将内容读入地址范围结构的链表.

MEM-stats.h:

#ifndef MEM_STATS_H

#define MEM_STATS_H

#include

#include

#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 */

MEM-stats.c:

#define _POSIX_C_SOURCE 200809L

#define _BSD_SOURCE

#include

#include

#include

#include

#include

#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;

}

一个使用上面例子的例子程序:

#include

#include

#include

#include

#include

#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 $@

请注意,上述Makefile中的三个缩进行必须使用制表符,而不是空格.看起来编辑器将标签转换为空格,因此您需要修正,例如使用

sed -e 's|^ *|\t|' -i Makefile

如果您不修复缩进,并在Makefile中使用空格,您会看到类似于***缺失分隔符的错误消息.停止.

一些编辑器自动将标签按键转换为多个空格,因此您可能需要深入了解您使用的任何编辑器的编辑器设置.通常,编辑者保持粘贴的标签字符不变,所以您可以随时尝试从另一个程序粘贴选项卡.

要编译并运行,保存上述文件并运行

make

./example 0

打印示例程序本身使用的内存范围.如果您想要看到PulseAudio守护程序使用的内存范围,请运行

./example $(ps -o pid= -C pulseaudio)

请注意,标准访问限制适用.普通用户只能看到作为该用户运行的进程的内存范围;否则您需要超级用户权限(sudo或类似).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值