C++面试再进阶

1、C++定义数组有大小限制吗?如何定义一个长度为一百万的数组?

答:定义数组大小的限制主要是看数组定义在内存的哪个区域内。局部非静态的数组,空间在程序的栈上分配,不同平台的栈大小不同:SunOS/Solaris是8M,Linux是10M,Windows是1M,AIX是64M,都是可以调整的。也就是说,数组大小的限制就是堆或栈或全局存储区大小的限制。如果想定义长度一百万的数组可以将数组申明在全局存储区或堆上,这些区域大小是比栈大很多的。

2、死锁原因及解决、避免办法

答:死锁的四个条件是:1、互斥,2、请求与保持,3、不可抢占,4、循环等待条件。这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
死锁避免的基本思想是:系统对进程发出每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,如果分配后系统可能发生死锁,则不予分配,否则予以分配。
写程序时应该尽量避免同时获得多个锁,如果一定有必要这么做,则有一个原则:如果所有线程在需要多个锁时都按相同的先后顺序获得锁,则不会出现死锁。(避免条件4的成立)

3、HTTP常见的头部信息有哪些?

答:
一段典型的请求

GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1
Host: net.tutsplus.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120
Pragma: no-cache
Cache-Control: no-cache

一段典型的应答

HTTP/1.x 200 OK
Transfer-Encoding: chunked
Date: Sat, 28 Nov 2009 04:36:25 GMT
Server: LiteSpeed
Connection: close
X-Powered-By: W3 Total Cache/0.8
Pragma: public
Expires: Sat, 28 Nov 2009 05:36:25 GMT
Etag: "pub1259380237;gz"
Cache-Control: max-age=3600, public
Content-Type: text/html; charset=UTF-8
Last-Modified: Sat, 28 Nov 2009 03:50:37 GMT
X-Pingback: http://net.tutsplus.com/xmlrpc.php
Content-Encoding: gzip
Vary: Accept-Encoding, Cookie, User-Agent
<!-- ... rest of the html ... -->
  • Host 一个HTTP请求会发送至一个特定的IP地址,但是大部分服务器都有在同一IP地址下托管多个网站的能力,那么服务器必须知道浏览器请求的是哪个域名下的资源。
  • User-Agent 浏览器名和版本号,操作系统名和版本号,默认语言。
  • Accept-Language 用户的默认语言设置。如果网站有不同的语言版本,那么就可以通过这个信息来重定向用户的浏览器。
  • Accept-Encoding 大部分的现代浏览器都支持gzip压缩,并会把这一信息报告给服务器。这时服务器就会压缩过的HTML发送给浏览器。这可以减少近80%的文件大小,以节省下载时间和带宽。
  • If-Modified-Since 如果一个页面已经在你的浏览器中被缓存,那么你下次浏览时浏览器将会检测文档是否被修改过。
  • Cookie 顾名思义,他会发送你浏览器中存储的Cookie信息给服务器。
  • Referer 顾名思义, 头部将会包含referring url信息。
  • Authorization 当一个页面需要授权,浏览器就会弹出一个登陆窗口,输入正确的帐号后,浏览器会发送一个HTTP请求,但此时会包含这样一个头部。

4、Git和SVN的区别,Git对比SVN的优势有哪些?

答:主要答案可以参考这篇文章
这里我总结一下:

  • 1.GIT是分布式的,SVN是集中式的。这是Git和SVN的核心区别。使用Git开发时,每一个开发人员的电脑上有一个Local Repository,所以即使没有网络也一样可以Commit,查看历史版本记录,创建项 目分支等操作,等网络再次连接上Push到Server端。
  • 2.Git把内容按元数据方式存储,而SVN是按文件。
  • 3.Git没有一个全局版本号,而SVN有。
  • 4.Git的内容的完整性要优于SVN:GIT的内容存储使用的是SHA-1哈希算法。

总之,Git的特点是版本控制可以不依赖网络做任何事情,相比于SVN,它对分支和合并有更好的支持。

5、不使用标准库函数实现函数char* int2str(unsigned int values)

char* int2str(unsigned int values)  
{  
    int len = 0;  
    const char digits[11] = "0123456789";  
    unsigned int tvalue = values;  
    while(tvalue >= 100)  
    {  
        tvalue /= 100;  
        len += 2;  
    }  
    if (tvalue > 10)  
        len += 2;  
    else if(tvalue > 0)  
        len++;  
  
    char* crtn = new char[len+1];  
    crtn += len;  
    *crtn = '\0';  
    do   
    {  
        *--crtn = digits[values%10];  
    } while (values /= 10);  
  
    return crtn;      
}  

6、有两个双向循环链表A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两链表中data值相同的结点删除

struct node   
{ 
    int data;   
    struct node *front,*next;   
};   
  
BOOL DeteleNode(Node *pHeader, DataType Value)  
{  
    if (pHeader == NULL) return;  
  
    BOOL bRet = FALSE;  
    Node *pNode = pHead;  
    while (pNode != NULL)  
    {  
        if (pNode->data == Value)  
        {  
            if (pNode->front == NULL)  
            {  
                pHeader = pNode->next;  
                pHeader->front = NULL;  
            }  
            else  
            {  
                if (pNode->next != NULL)  
                {  
                    pNode->next->front = pNode->front;  
                }  
                pNode->front->next = pNode->next;  
            }  
  
            Node *pNextNode = pNode->next;  
            delete pNode;  
            pNode = pNextNode;  
  
            bRet = TRUE;   
            //不要break或return, 删除所有  
        }  
        else  
        {  
            pNode = pNode->next;  
        }  
    }  
  
    return bRet;  
}  
  
void DELETE(Node *pHeadA, Node *pHeadB)  
{  
    if (pHeadA == NULL || pHeadB == NULL)  
    {  
        return;  
    }  
  
    Node *pNode = pHeadA;  
    while (pNode != NULL)  
    {  
        if (DeteleNode(pHeadB, pNode->data))  
        {  
            if (pNode->front == NULL)  
            {  
                pHeadA = pNode->next;  
                pHeadA->front = NULL;  
            }  
            else  
            {  
                pNode->front->next = pNode->next;  
                if (pNode->next != NULL)  
                {  
                    pNode->next->front = pNode->front;  
                }  
            }  
            Node *pNextNode = pNode->next;  
            delete pNode;  
            pNode = pNextNode;  
        }  
        else  
        {  
            pNode = pNode->next;  
        }  
    }  
} 

7、VC程序如何通过崩溃地址定位代码的出错行?

答:主要以参考这篇文章
可以通过map文件和cod文件来定位出错行。
1.生成map文件,在VS2008中设置方法是property->Configuration Properties->Linker->Debugging 中的Generate Map File选择Yes(/MAP);
2.生成cod文件,在VS2008中设置方法是property->Configuration Properties->C/C++->output Files中Assembler OutPut中选择Assembly,Maching Code and Source(/FAcs)
3.通过崩溃地址在map文件中找到出错的函数;
4.在cod文件中找到对应的函数,然后计算相对偏移地址以找到对应的出错行。

还有通过Dump文件和WinDbg调试等方法。想要程序既不崩溃又能快速定位到出错代码终极办法就是SEH+MiniDump,参考这篇文章

阅读 297

推荐阅读

学技术简单记,吴尼玛带你记笔记。

0 人关注
36 篇文章
专栏主页