c ++将argv读入unsigned char固定大小:分段错误
c++ reading argv into unsigned char fixed size: Segmentation fault
我正在尝试将命令行参数读入固定大小的无符号字符数组。我遇到分段错误。
我的代码:
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <memory.h>
unsigned char key[16]={};
int main(int argc, char** argv){
std::cout << "Hello!" << std::endl;
long a = atol(argv[1]);
std::cout << a << std::endl;
memcpy(key, (unsigned char*) a, sizeof key);
// std::cout << sizeof key << std::endl;
// for (int i = 0; i < 16; i++)
// std::cout << (int) (key[i]) << std::endl;
return 0;
}
我做错了什么?
调用程序:
编译:g++ main.cpp
执行:./a.out 128
您收到 SEGV 是因为您的地址错误:您将值转换为地址。加上大小是目标之一,应该是源的大小
编译器发出警告,这从来都不是好事,您应该考虑到这一点,因为那正是您的错误:
xxx.c:12:38: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
memcpy(key, (unsigned char*) a, sizeof key);
^
像这样修复:
memcpy(key, &a, sizeof(a));
顺便说一句,您不必用 16 个字节声明 key
。像这样分配它会更安全:
unsigned char key[sizeof(long)];
并且当您打印字节时,也要迭代直到 sizeof(long)
,否则您最后只会打印垃圾字节。
这是一个使用 uint64_t
的修复建议(来自 stdint.h
的无符号 64 位整数,它可以精确控制大小),key
的零初始化和使用 strtoll
:
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <memory.h>
#include <stdint.h>
unsigned char key[sizeof(uint64_t)]={0};
int main(int argc, char** argv){
std::cout << "Hello!" << std::endl;
uint64_t a = strtoll(argv[1],NULL,10);
memcpy(key, &a, sizeof a);
for (int i = 0; i < sizeof(key); i++)
std::cout << (int) (key[i]) << std::endl;
return 0;
}
(如果要处理signed,改成int64_t
即可)
小端架构测试:
% a 10000000000000
Hello!
0
160
114
78
24
9
0
0
您似乎复制了太多数据。
我还为 memcpy 添加了 &a。
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <memory.h>
unsigned char key[16]={};
int main(int argc, char** argv)
{
memset(key,0x0, sizeof(key));
std::cout << "Hello!" << std::endl;
long a = atol(argv[1]);
std::cout << a << std::endl;
// the size parameter needs to be the size of a
// or the lesser of the size of key and a
memcpy(key,(void *) &a, sizeof(a));
std::cout << "size of key " << sizeof(key) << "\n";
std::cout << "key " << key << "\n";
for (int i = 0; i < 16; i++)
std::cout << " " << i << " '" << ((int) key[i]) << "'\n";
return 0;
}
我正在尝试将命令行参数读入固定大小的无符号字符数组。我遇到分段错误。
我的代码:
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <memory.h>
unsigned char key[16]={};
int main(int argc, char** argv){
std::cout << "Hello!" << std::endl;
long a = atol(argv[1]);
std::cout << a << std::endl;
memcpy(key, (unsigned char*) a, sizeof key);
// std::cout << sizeof key << std::endl;
// for (int i = 0; i < 16; i++)
// std::cout << (int) (key[i]) << std::endl;
return 0;
}
我做错了什么?
调用程序:
编译:g++ main.cpp
执行:./a.out 128
您收到 SEGV 是因为您的地址错误:您将值转换为地址。加上大小是目标之一,应该是源的大小
编译器发出警告,这从来都不是好事,您应该考虑到这一点,因为那正是您的错误:
xxx.c:12:38: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
memcpy(key, (unsigned char*) a, sizeof key);
^
像这样修复:
memcpy(key, &a, sizeof(a));
顺便说一句,您不必用 16 个字节声明 key
。像这样分配它会更安全:
unsigned char key[sizeof(long)];
并且当您打印字节时,也要迭代直到 sizeof(long)
,否则您最后只会打印垃圾字节。
这是一个使用 uint64_t
的修复建议(来自 stdint.h
的无符号 64 位整数,它可以精确控制大小),key
的零初始化和使用 strtoll
:
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <memory.h>
#include <stdint.h>
unsigned char key[sizeof(uint64_t)]={0};
int main(int argc, char** argv){
std::cout << "Hello!" << std::endl;
uint64_t a = strtoll(argv[1],NULL,10);
memcpy(key, &a, sizeof a);
for (int i = 0; i < sizeof(key); i++)
std::cout << (int) (key[i]) << std::endl;
return 0;
}
(如果要处理signed,改成int64_t
即可)
小端架构测试:
% a 10000000000000
Hello!
0
160
114
78
24
9
0
0
您似乎复制了太多数据。 我还为 memcpy 添加了 &a。
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <memory.h>
unsigned char key[16]={};
int main(int argc, char** argv)
{
memset(key,0x0, sizeof(key));
std::cout << "Hello!" << std::endl;
long a = atol(argv[1]);
std::cout << a << std::endl;
// the size parameter needs to be the size of a
// or the lesser of the size of key and a
memcpy(key,(void *) &a, sizeof(a));
std::cout << "size of key " << sizeof(key) << "\n";
std::cout << "key " << key << "\n";
for (int i = 0; i < 16; i++)
std::cout << " " << i << " '" << ((int) key[i]) << "'\n";
return 0;
}