我不确定为什么下面的代码片段没有做到它应该做的事情 做。在第二个循环中返回数字0到9将是主意。 * scp是一个指针 到分配给程序的内存区域。
unsigned char* scp = (unsigned char*)(0x8e000000);
scp_size = 10;
for(i = 0; i < scp_size; i++, scp++) {
*scp = i;
}
}
scp = (unsigned char*)(0x8e000000);
for(i = 0; i < scp_size; i++, scp++) {
printf("Data read[%d]: %d\n", i, *scp);
}
然而,实际输出完全不同:
[exec] Data read[0]: 3
[exec]
[exec] Data read[1]: 3
[exec]
[exec] Data read[2]: 3
[exec]
[exec] Data read[3]: 3
[exec]
[exec] Data read[4]: 128
[exec]
[exec] Data read[5]: 35
[exec]
[exec] Data read[6]: 32
[exec]
[exec] Data read[7]: 1
[exec]
[exec] Data read[8]: 18
[exec]
[exec] Data read[9]: 146
如果我把这些东西与指针或任何其他想法混在一起可能出错了,那么任何人都有想法吗?非常感谢
答案 0 :(得分:6)
您发布的代码是正确的。问题不在这里。
您要写入的特殊内存区域存在问题。要么它是只读的,要么不能直接写,或者用这种方式写。如果您告诉我们运行此代码的平台,也许有人可以帮助您。
正如@Jari指出的那样,如果你使用数组访问它会更干净。
答案 1 :(得分:3)
您对printf
的格式规范与您实际传入的格式不符,因此所有投注均已关闭。 scp
是指向无符号字符的指针,但是您为printf
提供了%d
格式说明符,这意味着整数。由于printf
采用varargs,编译器无法将*scp
自动提升为int。实际上(在32位整数系统上),它正在读取你的字符和三个垃圾字节并将其解释为整数,然后打印该值。
尝试printf("Data read[%d]: %d\n", i, static_cast<int>(*scp));
所有这一切,你不能只写那样的任意内存地址。分配内存使用:
unsigned char* scp = new unsigned char*[10];
答案 2 :(得分:2)
这有效:
int main(int argc, char* argv[])
{
unsigned char arr[10];
unsigned char* scp = arr;
int scp_size = 10;
int i = 0;
for(i = 0; i < scp_size; i++, scp++) {
*scp = i;
}
scp = arr;
for(i = 0; i < scp_size; i++, scp++) {
printf("Data read[%d]: %d\n", i, *scp);
}
return 0;
}
是否在写入和读取之间更改了内存?
答案 3 :(得分:1)
你有没有理由不使用scp指向内存的数组访问?我在想这样的事情:
for(i = 0; i < scp_size; i++) {
scp[i] = i;
}
for(i = 0; i < scp_size; i++) {
printf("Data read[%d]: %d\n", i, scp[i]);
}
答案 4 :(得分:1)
可能您正在用户模式下运行,其中指针是虚拟地址。但是你的0x8e000000是一个物理地址。你不能只是“关闭”MMU而不破坏机器上运行的所有其他代码,你需要找到你的操作系统内核调用来创建到特定物理地址空间的虚拟映射。在Linux上,您可以mmap /dev/mem
或/ dev / kmem`来完成此任务。
答案 5 :(得分:0)
代码看起来应该对我有用(虽然我会使用数组)。我会尝试使用调试器逐步完成它,并观察内存发生的变化或设置观察点。
答案 6 :(得分:0)
我怀疑发生了两件事之一:
也许第二个循环中的printf可能会误解第三个参数(* scp)。请记住,printf不是类型安全的。 * scp可能被解释为int,因为您使用的是%d格式说明符 - 似乎没有unsigned char的格式说明符。试试这个:
scp = (unsigned char*)(0x8e000000);
for(i = 0; i < scp_size; i++, scp++) {
int val = *scp;
printf("Data read[%d]: %d\n", i, val);
}
或者,内存块的内容在您写入和读取之间发生变化。它是由另一个进程/线程/ t或某种设备映射缓冲区写入的共享内存吗?你能否删除另一个进程或设备写入它的可能性?
答案 7 :(得分:0)
可能内存区域不可写?
在下面看到了。这应该有所帮助: -
探索您的内存管理功能和/或内存映射 硬件,和/或您的操作系统,和/或您的系统监视器。
如果您可以表示保证为特定内存的值 地址受系统限制,作为C指针,而不是你可以做到的 你的建议。你可能会被迫在装配中这样做,甚至 那么,在许多操作系统上,你必须构建类似的东西 内核驱动程序,以便分配除虚拟内存以外的任何内容。
也就是说,内存映射I / O仍然很常见。但内存映射 绑定到特定硬件地址空间的I / O实际上并不是什么东西 你可以严格地谈谈C的背景。这是一个问题 comp.arch,或专门用于您的硬件或OS平台的论坛。
有Linux内核驱动程序可以处理内存映射的I / O. 各种设备,可能不会太难分析。我看看 一些ISA驱动器控制器或旧声卡可能的地方 找到例子(但我只是猜测)。
答案 8 :(得分:0)
使用0x8e00做你正在做的事情是不好的做法...除非你有一个特定的原因,比如它是内存映射IO寄存器或其他东西。你需要先告诉我们你想要做的事情;乍一看这是不好的代码,你是混合类型,抓住看起来像随机存储位置等等。
答案 9 :(得分:-1)
如果我假设循环变量i是一个int,那么在每一步你都要写一个整数(i)从0x8e000000开始(占用sizeof(int)字节数)并通过sizeof(unsigned char)递增scp字节数。由于int和char(大多数系统上为4和1)的大小不同,因此scp ++不会使指针前进正确的字节数。所以下一次你做一个* scp = i,你将覆盖前一个整数第三个字节。