小编Eva*_*ran的帖子

阻塞套接字返回EAGAIN

我在Linux上的一个项目使用了阻塞套接字.事情发生非常连续,所以非阻塞只会让事情变得更复杂.无论如何,我发现经常一个recv()调用返回-1errno设置为EAGAIN.

man页面只是真正提到非阻塞套接字发生这种情况,这是有道理的.如果没有阻塞,则套接字可能可用,也可能不可用,因此您可能需要重试.

什么会导致阻塞套接字发生?我可以做些什么来避免它吗?

目前,我处理它的代码看起来像这样(我在错误时抛出异常,但除此之外它是一个非常简单的包装器recv()):

int ret;
do {
    ret = ::recv(socket, buf, len, flags | MSG_NOSIGNAL);
} while(ret == -1 && errno == EAGAIN);


if(ret == -1) {
    throw socket_error(strerror(errno));
}
return ret;
Run Code Online (Sandbox Code Playgroud)

这甚至是正确的吗?这种EAGAIN情况经常受到打击.

编辑:我注意到的一些可能相关的事情.

  1. 我在套接字上设置了读取超时setsockopts(),但设置为30秒.这种EAGAIN情况经常发生在每30秒一次.修正我的调试有缺陷,EAGAIN不会像我想象的那样经常发生.也许是超时触发.

  2. 为了连接,我希望能够连接超时,所以我暂时将套接字设置为非阻塞.该代码如下所示:

    int      error = 0;
    fd_set   rset;
    fd_set   wset;
    int      n;
    const SOCKET sock = m_Socket;
    
    // set the socket …
    Run Code Online (Sandbox Code Playgroud)

c c++ sockets linux

7
推荐指数
1
解决办法
3万
查看次数

fopen'd文件的默认输入和输出缓冲?

因此,FILE流可以同时具有输入和输出缓冲区.您可以使用调整输出流setvbuf(我不知道任何使用输入缓冲区大小和行为的方法).

此外,默认情况下缓冲区是BUFSIZ(不确定这是POSIX还是C的东西).这对于stdin/ stdout/ 这意味着什么stderr,但新打开的文件的默认值是什么?它们是否针对输入和输出进行缓冲?或者也许只有一个?

如果它是缓冲的,输出默认为阻塞或行模式吗?

编辑:我已经做了一些测试,看看Jonathan Leffler的回答如何影响现实世界的节目.看来如果你做了一个读,那么写.写入将导致输入缓冲区的未使用部分完全丢弃.事实上,将会有一些寻求将事物保持在正确的文件偏移量.我用这个简单的测试程序:

/* input file contains "ABCDEFGHIJKLMNOPQRSTUVWXYZ" */
#include <stdio.h>
#include <stdlib.h>

int main() {

    FILE *f = fopen("test.txt", "r+b");
    char ch;
    fread(&ch, 1, 1, f);
    fwrite("test", 4, 1, f);
    fclose(f);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

导致以下系统调用:

read(3, "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", 4096) = 27 // attempt to read 4096 chars, got 27
lseek(3, -26, SEEK_CUR)                 = 1        // at this point, I've done my write already, so forget the …
Run Code Online (Sandbox Code Playgroud)

c buffer file stream

7
推荐指数
1
解决办法
6622
查看次数

用于十六进制输入的QValidator

我有一个Qt小部件,它只接受十六进制字符串作为输入.将输入字符限制为非常简单[0-9A-Fa-f],但我想让它显示"bytes"之间的分隔符,例如,如果分隔符是空格,而用户类型0011223344我希望行编辑显示00 11 22 33 44现在如果用户按下退格键3次,然后我想要它显示00 11 22 3.

几乎拥有我想要的东西,到目前为止只有一个微妙的错误,涉及使用删除键删除分隔符.有没有人有更好的方法来实现这个验证器?到目前为止,这是我的代码:

class HexStringValidator : public QValidator {
public:
    HexStringValidator(QObject * parent) : QValidator(parent) {}

public:
    virtual void fixup(QString &input) const {
        QString temp;
        int index = 0;

            // every 2 digits insert a space if they didn't explicitly type one 
        Q_FOREACH(QChar ch, input) {
            if(std::isxdigit(ch.toAscii())) {

                if(index != 0 && (index & 1) == 0) {
                    temp += ' ';
                }

                temp …
Run Code Online (Sandbox Code Playgroud)

c++ qt qlineedit

7
推荐指数
2
解决办法
8224
查看次数

是否允许在std :: string的实现中进行此优化?

我只是想着实施std::string::substr.它返回一个新std::string对象,这对我来说似乎有点浪费.为什么不返回一个引用原始字符串内容的对象,并且可以隐式赋值给std::string?一种对实际复制的懒惰评价.这样的类看起来像这样:

template <class Ch, class Tr, class A>
class string_ref {
public:
    // not important yet, but *looks* like basic_string's for the most part

private:
    const basic_string<Ch, Tr, A> &s_;
    const size_type pos_;
    const size_type len_;    
};
Run Code Online (Sandbox Code Playgroud)

这个类的公共接口将模仿真实的所有只读操作std::string,因此使用将是无缝的.std::string然后可以有一个新的构造函数,string_ref因此用户永远不会更聪明.在您尝试"存储"结果的那一刻,您最终会创建一个副本,因此引用没有真正的问题指向数据,然后在其背后进行修改.

想法是这样的代码:

std::string s1 = "hello world";
std::string s2 = "world";
if(s1.substr(6) == s2) {
    std::cout << "match!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

std::string总共不会构造2个对象.对于执行大量字符串操作的代码来说,这似乎是一种有用的优化.当然,这不仅适用于std::string任何可以返回其内容子集的类型.

据我所知,没有实现这样做.

我想问题的核心是:

给定一个可以根据需要隐式转换为类的类std::string,是否符合库编写者的标准,将成员的原型更改为返回类型?或者更一般地说,库编写者是否有余地在这些类型的情况下作为优化返回"代理对象"而不是常规对象?

我的直觉是,这是不允许的,原型必须完全匹配.鉴于您不能单独重载返回类型,这将使​​图书馆编写者无法利用这些类型的情况.就像我说的,我认为答案是否定的,但我想我会问:-).

c++ optimization standard-library proxy-object

7
推荐指数
1
解决办法
392
查看次数

为什么我错过了Qt Multimedia功能?

我是Qt的新手,我正在创建一个简单的应用程序,它将播放音频文件.我意识到在写作时我缺少用于音频的Qt Multimedia API:

#include <QAudioOutput>
Run Code Online (Sandbox Code Playgroud)

..我知道没有这样的文件.

我下载了最新的Qt SDK框架,但是找不到添加这些API的方法.我正在使用Qt creator IDE.

有没有办法让多媒体功能可以作为插件或其他方式工作?

谢谢.

c++ audio multimedia qt4

7
推荐指数
2
解决办法
1万
查看次数

链接到Qt中的共享库

我刚刚创建了tinyxml作为共享库,并想知道如何链接它.这是如何完成的?

c++ qt shared-libraries

7
推荐指数
1
解决办法
9464
查看次数

查找STL迭代器的所有者

有什么方法可以找到迭代器指向的容器吗?具体来说,我希望能够找到std::vector特定的指向,std::vector::iterator以便我可以检查范围,而不必实际传递对该向量的引用.

如果(我怀疑)答案是否定的,为什么不呢?

编辑:感谢您提供一些快速且(大部分)准确的答案.Evan Teran指甲.我根本没有考虑优化,但现在很明显.

有几个人问我想做什么.这没什么特别重要的.我有一个对象,它用向量和指向向量的迭代器初始化.如果我可以使用迭代器初始化对象,这将是可爱和方便的,因为然后我可以将vector::iterators直接转换为此对象(这听起来很奇怪,但在特定情况下确实有意义).但它根本不重要.

c++ iterator stl

6
推荐指数
2
解决办法
1483
查看次数

关于在C++中将数组存储在std :: vector中的问题

我不清楚以下情况.

首先,这段代码编译得很好:

#include <vector>

typedef struct{
    int x1,x2,x3,x4;
}  ints;

typedef std::vector<ints> vec;

int main(){
    vec v;
    ints a = {0,1,2,3};
    v.push_back(a);
}
Run Code Online (Sandbox Code Playgroud)

以下代码几乎相同:

#include <vector>

typedef std::vector<int[4]> vec;

int main(){
    vec v;
    int a[4] = {0,1,2,3};
    v.push_back(a);
}
Run Code Online (Sandbox Code Playgroud)

但它会抛出我将在最后包含的极长的错误输出.为什么编译器对这两个程序的处理方式如此不同?这绝对不直观.

这是我的系统上使用g ++编译时抛出的编译器错误:

[mattg@pigott Test]$ g++ test2.cpp -o test2
In file included from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/i586-redhat-linux/bits/c++allocator.h:34,
                 from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/allocator.h:48,
                 from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/vector:62,
                 from test2.cpp:2:
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/ext/new_allocator.h: In member function ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = int [4]]’:
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/stl_vector.h:737:   instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with …
Run Code Online (Sandbox Code Playgroud)

c++ compiler-construction gcc g++ stdvector

6
推荐指数
3
解决办法
8789
查看次数

为什么不是std :: string :: max_size()== std :: string :: allocator :: max_size()

最近我注意到以下陈述并非如此std::string s.

s.max_size() == s.get_allocator().max_size();
Run Code Online (Sandbox Code Playgroud)

我发现这很有意思,默认情况下std::string会使用std::allocator<char>它具有理论极限size_type(-1)(是的,我知道我假设2的补码,但这与实际问题无关).我知道实际的限制将远远小于此.在典型的32位x86系统上,内核将占用2GB(可能是1GB)的地址空间,从而留下更小的实际上限.

无论如何,GNU libstdc ++ std::basic_string<>::max_size()似乎返回相同的值,无论它使用什么分配器(如类似1073741820).

所以问题仍然存在,为什么不std::basic_string<>::max_size()回归get_allocator().max_size()呢?在我看来,这是假设的上限.如果分配很短,它只会扔一个std::bad_alloc,所以为什么不尝试?

这更像是一种好奇心,我只是想知道为什么这两者至少在这一个实现中被单独定义.

c++ stdstring allocator

6
推荐指数
1
解决办法
1094
查看次数

MongoCursorException'无法获取响应头'

我正在使用PHP和mongodb开发一个网站.我用PECL-mongo访问mongodb ,并且遇到了烦恼.我时不时地得到这样的错误(我已经对这些路径进行了匿名)

Fatal error: Uncaught exception 'MongoCursorException' with message 'couldn't get response header' in
    /PATH/index.php:38 Stack trace: #0 
    /PATH/index.php(38): MongoCursor->rewind() #1 
    /PATH/template.inc(29): get_sidebar() #2 
    /PATH/index.php(13): 
    require_once('PATH/...') #3 {main} thrown in PATH/index.php on line 38
Run Code Online (Sandbox Code Playgroud)

根据文档,这意味着:

驱动程序无法从数据库中获取回复标头,因此它放弃了.检查数据库是否仍在运行并且网络已连接,然后再次尝试查询.

但我知道数据库已启动,因为我在我自己的机器上本地执行环回.没有与外界联系.

再试一次经常有效.这可能是PHP的mongo驱动程序中的一个错误吗?这可能是一个"错误编译"的问题(我从源代码编译,但有非常良性的标志,-march=native -O2)?

谁看过这个吗?

搜索周围,我只看到一些愚蠢的Facebook游戏的引用有相同的错误.

编辑:我刚刚将我的PECL驱动程序降级到1.1.4版本,到目前为止,问题似乎已经消失.所以这可能只是1.2.x系列中的一个错误.如果有人能够对它有所了解,那就太好了.

编辑:我在这里没有做任何复杂的事情,有问题的代码看起来像这样:

$m = new Mongo();
$collection = $m->my_db->collection;
$results = $collection->find(array("favorite"=>true))->limit(5);
Run Code Online (Sandbox Code Playgroud)

php mongodb mongodb-php

6
推荐指数
1
解决办法
1661
查看次数