这道笔试题竟然运行不出错_twitter

#读者提供的面试题

下面这张截图是一个读者在面试的时候遇到的题目,是哪个公司的我就不说出来了,我在微信朋友圈发了这个题目后,有几个好友给我留言说自己也写了这道题。

题目:下面这段代码有什么问题?这道笔试题竟然运行不出错_指针_02

#后续

然后我就用这个图片发了朋友圈,很多人也回复了,天资跟我差不多的人呢,都看出来了就是 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、入参ab都是void类型的指针,不清楚ab指向buff的长度是否都为size?size不要设置成int,最好设置成unsigned int, 而且ab入参一定不能代入const xxxxx *类型的实参;

2、 进入函数体之后应该首先判断size是否小于等于0ab是否为NULL,如果size小于等于0,或者ab存在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。

祝大家周末愉快!

 

这道笔试题竟然运行不出错_指针_03

这道笔试题竟然运行不出错_c++11_04