相关疑难解决方法(0)

如何(计算)C++中的goto和longjmp?

我通常不会编写C++代码,但我的一个奇怪的comp sci朋友厌倦了查看我精彩的FORTRAN程序并挑战我用C++重写其中一个,因为他更喜欢我的C++代码.(我们在这里投入资金.)确切的术语是它需要在现代C++编译器中进行编译.也许他讨厌一个好的conio.h - 我不知道.

现在我意识到在C++中有很好的写作方式,但是我想通过尽可能使我的C++版本成为FORTRAN-esque来获得个人胜利.对于奖励积分,当我转换代码时,这可能会节省一些时间和精力.

所以!这带我进入以下相关查询:

在gotos:

  1. 你是如何工作的?
  2. 对C++中的gotos有什么限制?
  3. 有关范围的任何担忧?(我将尽可能地尝试全局范围,但你永远不会知道.)
  4. 如果我使用GCC扩展转到void指针数组,是否有任何关于未定义行为的新问题等?


在longjmp上:

  1. 你如何安全地使用longjmp?
  2. C++中对longjmps的约束是什么?
  3. 它的作用范围是什么?
  4. 有什么特别的时刻,看起来longjmp应该是安全的,但实际上并不是我应该注意的吗?
  5. 如何使用longjmp模拟计算的goto?
  6. 如果我的程序中只有一个函数,那么使用longjmp over goto有什么明显的好处吗?

现在我的主要关注点是为此计算goto.看起来我可能会使用longjmp来完成这项工作,因为void指针数组不是C++标准的一部分,而是GCC特定的扩展.

c++ goto longjmp language-extension setjmp

12
推荐指数
2
解决办法
2915
查看次数

使用setjmp在C++对象上警告"可能会被破坏"

#include <setjmp.h>
#include <vector>

int main(int argc, char**) {
 std::vector<int> foo(argc);
 jmp_buf env;
 if (setjmp(env)) return 1;
}

用GCC 4.4.1编译上面的代码,g ++ test.cc -Wextra -O1,给出了这个令人困惑的警告:

/usr/include/c++/4.4/bits/stl_vector.h: In function ‘int main(int, char**)’:
/usr/include/c++/4.4/bits/stl_vector.h:1035: warning: variable ‘__first’ might be clobbered by ‘longjmp’ or ‘vfork’

stl_vector.h的第1035行是在构造foo时调用的vector(n,value)构造函数使用的辅助函数中.如果编译器可以找出参数值(例如它是一个数字文字),警告就会消失,所以我在这个测试用例中使用了argc,因为编译器无法确定它的值.

我猜这个警告可能是因为编译器优化了向量构造,所以它实际上发生在setjmp着陆点之后(当构造函数参数依赖于函数的参数时,这似乎就是这种情况).

我怎样才能避免这个问题,最好不必将setjmp部分分解为另一个函数?

不使用setjmp不是一个选项,因为我遇到了一堆需要使用它来进行错误处理的C库.

c++ longjmp

8
推荐指数
2
解决办法
7296
查看次数

SetJmp/LongJmp:为什么这会引发段错?

以下代码总结了我目前遇到的问题.我当前的执行流程如下,我在GCC 4.3中运行.

jmp_buf a_buf;
jmp_buf b_buf;

void b_helper()
{
    printf("entering b_helper");
    if(setjmp(b_buf) == 0)
    {
        printf("longjmping to a_buf");
        longjmp(a_buf, 1);
    }
    printf("returning from b_helper");
    return; //segfaults right here
}
void b()
{
    b_helper();
}
void a()
{
    printf("setjmping a_buf");
    if(setjmp(a_buf) == 0)
    {
        printf("calling b");
        b();
    }
    printf("longjmping to b_buf");
    longjmp(b_buf, 1);
}
int main()
{
    a();
}
Run Code Online (Sandbox Code Playgroud)

上述执行流程在b_helper返回后立即创建段错误.它几乎就像只有b_helper堆栈帧有效,并且它下面的堆栈被擦除.

任何人都可以解释为什么会这样吗?我猜这是一个GCC优化,它正在擦除未使用的堆栈帧或其他东西.

谢谢.

c++ gcc g++ segmentation-fault

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

如何将程序执行跳转到C中的特定地址?

我希望程序跳转到内存中的特定地址并继续从该地址执行.我考虑过使用,goto但我没有标签而只是内存中的地址.

无需担心从跳转地址返回.

编辑:使用GCC编译器

c c++

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

c/c ++可以在单个线程中执行preemeptive多任务处理吗?

C/C++中的抢先式多任务处理:某个计时器是否可以中断正在运行的线程并在任务之间切换?

使用绿色线程等的许多VM和其他语言运行时以这些术语实现; C/C++应用程序可以做同样的事情吗?

如果是这样,怎么样?

这将取决于平台,因此请根据特定平台对此的支持进行讨论; 例如,如果你有一些魔法可以SIGALRM在Linux上的处理程序中交换某种内部堆栈(也许使用longjmp?),那就太好了!


我问,因为我很好奇.

我已经工作了几年制作异步IO循环.在编写异步IO循环时,我必须非常小心,不要将昂贵的计算计算放入循环中,因为它会使DOS循环.

因此,我对可以采用异步IO循环以恢复甚至完全支持某种绿色线程或此类方法的各种方式感兴趣.例如,对活动任务进行采样和a中的循环迭代次数SIGALRM,然后如果检测到任务阻塞,则将其他所有内容移动到新线程,或者对此具有所需结果的一些狡猾变化.

最近在这方面有一些关于node.js的抱怨,而在其他地方,我看到过关于Go和Haskell等其他运行时的诱人评论.但是,让我们离开基本问题,你是否可以在C/C++中的单个线程中执行抢占式多任务处理

c c++ thread-safety green-threads

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

将C++接口中的longjmps隐藏到C代码中

为旧C代码生成C++ API的正确方法是什么?该代码广泛使用带有多个跳转目标的longjmp进行错误管理?

我的想法是编写一个函数来为每个使用过的目标设置跳转目标,例如:

void catchJumps() {
    if (setjmp(target1)) throw Error1(); //Error1 and Error2 are some exception classes
    if (setjmp(target2)) throw Error2();
    //...
}
Run Code Online (Sandbox Code Playgroud)

然后我会调用catchJumps每个使用C代码的C++函数(在每个范围内,更具体):

int some_wrapper() {
    catchJumps();
    callCFunction()

    for (int i = 0; i < 1000; i++) {
        catchJumps();
        callOtherCFunction();
    }

    catchJumps();
    callOneMoreCFunction();
    callEvenOneMoreCFunction();
}
Run Code Online (Sandbox Code Playgroud)

这是一种在不破坏堆栈的情况下捕获所有longjump的安全方法吗?我知道,longjmp进入不同的堆栈框架是危险的.现在我的函数catchJumps在另一个堆栈框架而不是调用some_wrapper.我希望(或者我甚至可以做到)catchJumps可以内联,所以框架是相同的,但我不知道.

对于要调用的作用域对象的所有析构函数,每个作用域中的调用(以及上面的循环之后)都是必需的,对吧?

如果这不是将longjmps"转换"为调用应用程序的断言的有效方法,那么我们还能做些什么呢?

c c++ api longjmp

5
推荐指数
1
解决办法
235
查看次数

C++和Qt:这是内存泄漏吗?(和一般问题)

在过去的两年里,我主要使用C进行编程(以前是一些Java),并决定使用Qt Creator和Qt库来学习C++.

我的问题是以下代码是否引入了内存泄漏:

    // filename is a QStringListIterator
    // dir is a QDir
    while (filename.hasNext()) {
            QString came_from_file(dir.filePath(filename.next()));
            QFile file(came_from_file);
            file.open(QFile::ReadOnly);
            file.readLine();
            while (!file.atEnd()) {
                    QString line(file.readLine());
                    do_something_with_stuff(line, came_from_file);
            }
    }
Run Code Online (Sandbox Code Playgroud)

具体来说,我不确定生成的dir.filePath(filename.next())QString 会发生什么.came_from_file一旦被复制,它是否被引用或指针丢失?它是否被"复制"(我认为它永远不会,直到更改,由于Qt容器的Copy-On-Write性质)?我应该用不同的方式写这个QString match = dir.file...吗?据我了解,这应该是平等的.

它还在Qt文档中说QFile将在析构函数中关闭()必要的文件.析构函数会被调用吗?变量确实"超出范围",但我仍然不确定这是否是所谓的RAII的情况.

我如何file指向不同的文件?

如果我将这样的变量传递给函数(我假设这是通过引用,因为函数do_something...是以这种方式定义的),然后它们超出范围,但是被函数插入到QHash/QMap/QSet中,会发生什么?他们被删除了,容器变得疯狂,还是有一些像ref那样花哨的小方案.在这一切背后算吗?或者只是简单地复制了这些值?

我之前已经意识到类似的问题,但我似乎无法通过阅读它们来解释这个问题,因为它们似乎是不同的情况.

如果代码或我的理解有问题,请纠正我.:)

谢谢,南蒂尔

c++ qt memory-leaks raii

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

是否在setjmp被破坏之前创建了对象?

jpeglib中,必须使用setjmp/longjmp来实现自定义错误处理.

有很多资源据说setjmp/longjmp与c ++不兼容(例如这个问题中的答案告诉他们确实与RAII一起使用),但是这个问题的答案是说析构函数被调用了.

我有这个例子(取自这里并修改了一下):

#include <iostream>
#include <csetjmp>

std::jmp_buf jump_buffer;

struct A
{
    A(){std::cout<<"A()"<<std::endl;}
    ~A(){std::cout<<"~A()"<<std::endl;}
};

void a(int count) 
{
    std::cout << "a(" << count << ") called\n";
    std::longjmp(jump_buffer, count+1);  // setjump() will return count+1
}

int main()
{
    // is this object safely destroyed?
    A obj;

    int count = setjmp(jump_buffer);
    if (count != 9) {
        a(count);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,析构函数被调用(如我所料),但它是标准行为吗?或者它是编译器的扩展,还是简单的UB?


输出:

A()
a(0) called
a(1) called
a(2) called
a(3) called
a(4) called …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer longjmp c++11

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

是否应该longjmp恢复堆栈?

据我了解,setjmp保存当前上下文,并且应该在调用时还原它longjmp。但是,下一段代码将显示15(我使用-g编译,没有进行任何优化)。我是不是误解了这种结构,还是想念其他东西?

#include <iostream>
#include <csetjmp>


std::jmp_buf jump_buffer;

int main()
{
    int a = 0;
    if (setjmp(jump_buffer) == 0) {
      a = 15;
      std::longjmp(jump_buffer, 42);
    }
    std::cerr << a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

免责声明:仅出于好奇而尝试使用它。直到最近我阅读了一些有关NASA编码准则的论文,并提到禁止使用这种控制结构流程之后,我才听说过这种结构。

因为代码是混合的,所以同时使用c和c ++标记,并且我认为实际的相关功能与c重度用户更相关,而不是c ++ ...:/

c c++ longjmp setjmp

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

问题与longjmp

我想使用longjmp来模拟goto指令.我有一个包含struct类型元素的数组DS(int,float,bool,char).我想跳到标有"lablex"的地方,其中x是DS [TOP] .int_val.我怎么处理这个?

示例代码:

...
jmp_buf *bfj;
...
stringstream s;s<<"label"<<DS[TOP].int_val;
bfj = (jmp_buf *) s.str();
longjmp(*bfj,1);
Run Code Online (Sandbox Code Playgroud)

但是我认为它有问题我该怎么办?

错误:

output.cpp:在函数'int main()'中:

output.cpp:101:错误:从类型'std :: basic_string,std :: allocator>'转换为无效的类型'__jmp_buf_tag(*)[1]'

c++ longjmp

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

在C/C++中将标签作为参数

我们有一个标签:

LABEL:
    //Do something.
Run Code Online (Sandbox Code Playgroud)

我们有一个功能.我们希望传递LABEL作为此函数的参数(否则我们无法访问函数中的标签),并且在某些情况下我们想要跳转此标签.可能吗?

我举一个例子(伪代码)来澄清:

GameMenu: //This part will be executed when program runs
//Go in a loop and continue until user press to [ENTER] key

while(Game.running) //Main loop for game
{
    Game.setKey(GameMenu, [ESCAPE]); //If user press to [ESCAPE] jump into GameMenu
    //And some other stuff for game
}    
Run Code Online (Sandbox Code Playgroud)

goto c++11

0
推荐指数
1
解决办法
544
查看次数