【问题标题】:Value of C++ int Mysteriously ChangesC++ int 值的神秘变化
【发布时间】:2013-10-11 23:29:15
【问题描述】:

所以我正在编写一个 c++ 类以使 c 中的 unix 套接字更容易一些。但是,每次我运行它都无法连接。端口的值在程序中途改变。 这是带有类的头文件:

#ifndef __Sockets__CHSocket__
#define __Sockets__CHSocket__
class Sock {
    int port;
    char host[16];
    int sock,maxLen;
    int bytes;
    long nHostAddress;
    struct hostent* pHostInfo;
    struct sockaddr_in dest;

public:
    Sock(int dom, int type);
    int connct(const char *host, int port);
    int bnd(const char *addr, int port);
    int lstn(int port);
    int snd(const char *toSend);
    int sndto(const char *msg, const char *dst);
    char* recv(int length);
    int accpt(int s, struct sockaddr *addr, socklen_t *addrlen);
    int clse();
};  
#endif /* defined(__Sockets__CHSocket__) */

这里是 CHSocket.cpp(缩写为实际运行的内容):

// Constructor definition
Sock::Sock(int dom, int type)
{
    bzero(&dest, sizeof(dest));
    if ((sock=socket(dom, type, 0)<0)) {
        cerr << "[!] Failed to create socket!;";
    }
    dest.sin_family=dom;
    memset(&dest, 0, sizeof(dest));
}

// Connect definition
int Sock::connct(const char *host, int port)
{
    char theHost[sizeof(host)];
    strcpy(theHost, host);
    pHostInfo=gethostbyname(theHost);
    memcpy(&nHostAddress,pHostInfo->h_addr,pHostInfo->h_length);

    dest.sin_addr.s_addr=nHostAddress;
    dest.sin_port = htons(port);
    if (connect(sock, (struct sockaddr *)&dest, sizeof(dest)) < 0)
    {
        cerr << "[!] Failed to connect socket!";
        return -1;
    }
    else
    {
        return 0;
    }
    return 0;
}

这里是 main.cpp:

int main()
{
    Sock test = Sock(AF_INET, SOCK_STREAM);
    test.connct("127.0.0.1", 3000);
    test.clse();
}

我在 osx 10.8 上使用 xcode 5。当我运行程序时,它告诉我它无法连接。我在 connect 函数的最开始和定义 pHostInfo 的行中放置了一些断点。 第一个断点,port的值为3000,第二个断点是49,是不是和connect问题有关?

更新:

程序现在运行,但它给了我以下输出:

[!] Failed to connect socket!Program ended with exit code: 0

这就是它在连接套接字失败时所做的。我有 netcat 在端口 3000 上侦听,并且我从另一个窗口成功连接。任何想法可能是什么问题?

【问题讨论】:

  • 您使用的是reserved identifier
  • 我并不是说要苛刻,但是对于像这样的函数名称,我会毫不犹豫地使用原始 API 而不是你的。
  • @syam 这与问题无关,但您仍然是正确的。现在已经不是 1987 年了,电脑有很多内存,不需要再为这个目的保存它了。
  • @ipinak 实际上是为了节省击键而不是记忆(在过去,在电传打字机/穿孔卡/任何东西上输入数据真的很痛苦),但 Ritchie 本人后来承认这是一个错误.而且我们说的更像是 1970 年而不是 1987 年。;)

标签: c++ macos sockets


【解决方案1】:
char theHost[sizeof(host)];

该行分配了足够的字节来存储 host 的大小,这是一个指向 char 的指针,它可能是 8。然后它会覆盖端口号,因为您没有在堆栈上分配足够的内存。您可能想要以下内容:

char *theHost = new char[strlen(host)+1]

然后在构造函数返回之前释放该内存:

delete [] theHost;

另外,更简单更好的是,您可以直接在对gethostbyname() 的调用中使用host 参数

编辑:(按照建议添加了释放)

【讨论】:

  • 如果您要推荐动态分配,值得一提的是需要稍后致电delete[]
  • @syam 智能指针可以解决内存泄漏问题,但我认为真正需要发生的是跳过分配并直接使用参数
【解决方案2】:
char theHost[sizeof(host)];

为您提供一个包含sizeof(char*) 空间的数组。您实际上需要strlen(host)+1 字节,因此可能会在后续strcpy 中覆盖内存。改变这一点需要支持 VLA(不作为标准存在)或不必要的动态分配。

使用host 代替theHost 会更容易。

【讨论】:

  • 根据编译器的不同,gccclang 支持 VLA 和 extension in C++.
  • @ShafikYaghmour 谢谢,我不知道。我已经更新了我的答案。
  • @chris 谢谢,另一个我没有意识到的细节。答案现已更新。
  • @chris:不再。 C 形式中从来没有它们,std::dynarray 已被删除/推迟。
  • @GManNickG,我确信最初的计划是两者兼有,我知道 std::dynarray 已移至 TS,但我认为 VLA 仍在。
猜你喜欢
  • 1970-01-01
  • 2019-10-15
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-20
相关资源
最近更新 更多