这道笔试题竟然运行不出错
#读者提供的面试题
下面这张截图是一个读者在面试的时候遇到的题目,是哪个公司的我就不说出来了,我在微信朋友圈发了这个题目后,有几个好友给我留言说自己也写了这道题。
题目:下面这段代码有什么问题?
#后续
然后我就用这个图片发了朋友圈,很多人也回复了,天资跟我差不多的人呢,都看出来了就是 if
判断的代码需要往上移动下,要不然呢,malloc
后没有释放,就会出现内存泄漏。
这个是基本的,还有一些后续的回复,有几个微信好友回复还是比较不错,在这里分享给大家。
#我写的测试源码
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int swap(void *a,void* b,int size)
{
void *p;
p = malloc(size);
if(size <= 0)
{
printf("error");
return -1;
}
memcpy(p,a,size);
memcpy(a,b,size);
memcpy(b,p,size);
free(p);
return 0;
}
int main()
{
char *a = "12344";
char *b = "adbde";
swap(a,b,5);
printf("a:%s\tb:%s\n",a,b);
return 0;
}
程序输出
a:adbde b:12344
--------------------------------
Process exited after 0.03298 seconds with return value 0
请按任意键继续. . .
#void* 指针
程序里面有一个 void
指针,这个需要注意下,void
指针是可以接收所有类型的指针的,但是其他类型的指针是不能直接接收void
指针的。
比如这样
#include "stdio.h"
int main()
{
void *p = NULL;
char *p1 = NULL;
p = p1;
return 0;
}
下面这样可能是有问题的
我说是可能有问题是因为GCC、ANSI C 的编译情况是不同的。
#include "stdio.h"
int main()
{
void *p = NULL;
char *p1 = NULL;
p1 = p;
return 0;
}
#程序有什么问题?
这段代码有以下几点问题:
1、入参a
和b
都是void
类型的指针,不清楚a
和b
指向buff的长度是否都为size?
size
不要设置成int
,最好设置成unsigned int
, 而且a
和b
入参一定不能代入const xxxxx *
类型的实参;
2、 进入函数体之后应该首先判断size
是否小于等于0
、a
和b
是否为NULL
,如果size
小于等于0
,或者a
和b
存在NULL
,那其他代码将毫无意义。
3、没有if(!p)
对malloc
进行判断直接使用p
,剩余内存较低情况下malloc
一片大内存是有可能fail
的,直接使用p
就会段错,而且不建议malloc
。
4、memcpy
时因并不明确a b
指针指向buff
的长度是否都为size
,存在内存越界风险。
综上述修改代码为:
int swap(void *a, void *b, uint32_t len_a, uint32_t len_b)
{
if ( !a || !b || !len_a || !len_b || len_a!=len_b ) {
printf("invalid param! \n");
return -1;
}
if ( a==b ) {
printf("the same! \n");
return 0;
}
uint32_t len = len_a;
char *p = (char *)malloc(len);
if (!p) {
printf("malloc fail! \n");
return -1;
}
memcpy(p,a,len);
memcpy(a,b,len);
memcpy(b,p,len);
free(p);
return 0;
}
#参考代码
//我写了一个swap:
//感谢读者LinuxEngine
typedef struct {
char byte[4];
} stdb_4;
typedef struct {
char byte[8];
} stdb_8;
void my_swap(void *p, void *q, size_t p_sz, size_t q_sz)
{
char buff[256];
if ( !p || !q ||!p_sz || !q_sz || p_sz != q_sz || p==q )
return;
int sz = p_sz;
if ( sz == 4 ) {
stdb_4 t = *(stdb_4 *)p;
*(stdb_4 *)p = *(stdb_4 *)q;
*(stdb_4 *)q = t;
return;
} else if ( sz == 8 ) {
stdb_8 t = *(stdb_8 *)p;
*(stdb_8 *)p = *(stdb_8 *)q;
*(stdb_8 *)q = t;
return;
}
while ( sz > sizeof(buff) ) {
my_swap (p, q, sizeof(buff));
p = (char *)p + sizeof(buff);
q = (char *)q + sizeof(buff);
sz -= sizeof(buff);
}
memcpy(buff, p, sz);
memcpy(p, q, sz);
memcpy(q, buff, sz);
}
#后续
感谢读者LinuxEngine给出的答案以及示例代码,大家如果看到有优化的地方,可以在评论区说出你的答案,写程序是一个非常严谨的事情,程序写得严谨了,该考虑到的问题都能想到了,大概率就能去除一些比较明显的bug。
祝大家周末愉快!