天道酬勤,学无止境

c++ , pthread and static callbacks. "this" returns a pointer to the base class inctead of the derived one (part 2)

this thread was started here but due to lack of an altogether good example (and in order to avoid delete all that question) it is re-written here.

So, in the following example, the void cppthread::ThreadedFunc() gets spawned to execute as a separate thread . Instead I would prefer void ThreadedWrite::ThreadedFunc() to be executed. How can I do that? (some more details follow after the code)

cppthread.hpp

#ifndef CPPTHREAD_HPP
#define CPPTHREAD_HPP

#include <pthread.h>

using namespace std;

class cppthread
{
    public:
        cppthread();
        virtual ~cppthread();

        virtual void threadedFunc();
        ///parentObj (ie "this" pte from caller") is 
        ///necessary in order to execute the correct
        ///threadedFunc() even when the derived class
        ///wants to spawn a thread.
        int spawn(void *parentObj = NULL);
        void terminate();

    protected:
        pthread_mutex_t mtx;
        bool exitThread;

    private:
        /* add your private declarations */
        int join();

        pthread_t threadId;
};

#endif /* CPPTHREAD_HPP */ 

cppthread.cpp

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

#include "cppthread.hpp"

void* threadCallback(void* obj);

cppthread::cppthread()
{
    exitThread = false;
    pthread_mutex_init(&mtx, NULL);

}


cppthread::~cppthread()
{
    if (!exitThread)
        terminate();
    pthread_mutex_destroy(&mtx);
}

void cppthread::threadedFunc()
{
    while ( !exitThread )
    {
        printf("Hello from cppthread::threadfunc. This should not be run once derived and redefined.\n");
    }
    if (exitThread)
    {
        printf("graceful exit from cppthread::threadfunc. This should not be run once derived and redefined.\n");
    }
    pthread_exit((void*)0);
}

int cppthread::spawn(void* parentObj)
{
    int ret;
    printf("parentObj = %p\n", parentObj);
    if (parentObj == NULL)
    {
        ret = pthread_create(&threadId, 0, &threadCallback, this);
        printf("cppthread_create with \"this\" \n");
    }
    else
    {
        ret = pthread_create(&threadId, 0, &threadCallback, parentObj);
        printf("cppthread_create with parentObj\n");
    }

    if (ret != 0)
    {
        printf("cppthread_create error\n");
        exit(EXIT_FAILURE);
    }
    else
    {
        //printf("cppthread::threadID= %lu\n",threadId);
    }
    return ret;
}

void cppthread::terminate()
{
    exitThread = true;
    join();
}

int cppthread::join()
{
    int status , ret;
    //printf("cppthread::join_threadID= %lu\n",threadId);
    ret = pthread_join(threadId,(void**)&status);
    if (ret != 0)
    {
        printf("cppthread_join error: ");
        switch (ret)
        {
            case EDEADLK: printf("deadlock\n"); break;
            case EINVAL: printf("thread not joinable\n"); break;
            case ESRCH: printf("threadID not found\n"); break;
            default : printf("unknown error\n"); break;
        }
    }
    return status;
}

//----------------------------------------------------------------------
void* threadCallback(void* obj)
{
    static_cast<cppthread*>(obj)->threadedFunc();
    return(0);
} // callback

threadedwrite.hpp

#ifndef THREADEDWRITE_HPP
#define THREADEDWRITE_HPP

#include "cppthread.hpp"

using namespace std;

class ThreadedWrite : public cppthread
{
    public:
        ThreadedWrite(ThreadedWrite* mySelf);
        virtual ~ThreadedWrite();

        void threadedFunc();
        void rrdupdate_thread();

        ///inherited significant members: from cppthread
        ///   int spawn();
        ///   void terminate();
        ///protected
        ///   pthread_mutex_t mtx;
        ///   bool exitThread;

    private:
        ThreadedWrite* instancePtr;
};

#endif /* THREADEDWRITE_HPP */ 

threadedwrite.cpp

#include <iostream>
#include "threadedwrite.hpp"


ThreadedWrite::ThreadedWrite(ThreadedWrite* mySelf):instancePtr(mySelf)
{
    cout << "instancePtr = " << instancePtr << endl;
}

ThreadedWrite::~ThreadedWrite()
{

}

void ThreadedWrite::threadedFunc()
{
    if ( !exitThread )
    {
        cout << "this is the ThreadedWrite::threadedFunc() running!" << endl;
    }
    else
    {
        cout << "ThreadedWrite::threadedFunc must exist now" << endl;
    }

    pthread_exit((void*)0);
}

void ThreadedWrite::rrdupdate_thread()
{
    cout << "about to spawn" << endl;
    spawn(instancePtr);
}

main.cpp

#include <iostream>

#include "threadedwrite.hpp"

using namespace std;

//-------main body------------------------------------------------------
int main(int argc, char* argv[])
{
    ThreadedWrite  thrrdupd(&thrrdupd);
    cout << "hello from main 1 " << &thrrdupd << endl;
    thrrdupd.rrdupdate_thread();
    cout << "hello from main 2 " << &thrrdupd << endl;
    return 0;
}

The above produces the output (for me):

instancePtr = 0x7fff39d17860
hello from main 1 0x7fff39d17860
about to spawn
parentObj = 0x7fff39d17860
cppthread_create with parentObj
hello from main 2 0x7fff39d17860
graceful exit from cppthread::threadfunc. This should not be run once derived and redefined.

So executing the above cppthread::spawn() call from within the derived class "ThreadedWrite" , actually provides a "this" pointer to callback() function that points to cppthread::ThreadedFunc(), instead of ThreadedWrite::ThreadedFunc().

You can also see that I tried (through the "instancePtr" infrastructure) to pass a pointer to the instance of "ThreadedWrite" back to the callback function. But this failed too.

Also, preferably I would like to keep cppthread class as generic as possible in order to be able to use it in may cases.

Mind you, if I remove "spawn(instancePtr)" from threadedwrite.cpp , and call the spawn from main.cpp like this

int main(int argc, char* argv[])
{
        ThreadedWrite  thrrdupd(&thrrdupd);
        cout << "hello from main 1 " << &thrrdupd << endl;
        thrrdupd.rrdupdate_thread();
        thrrdupd.spawn();
        cout << "hello from main 2 " << &thrrdupd << endl;
        return 0;
}

the output that I get Is the expected (and wanted) one and it looks like this:

instancePtr = 0x7ffd24b04ed0
hello from main 1 0x7ffd24b04ed0
about to spawn
parentObj = (nil)
cppthread_create with "this" 
hello from main 2 0x7ffd24b04ed0
this is the ThreadedWrite::threadedFunc() running!

评论

You need to wait for the thread to terminate before you return from main, because that destroys your object.

Otherwise you have a race condition:

  1. The thread is started.
  2. thrrdupd starts to be destoyed as you leave main.
  3. ~ThreadedWrite runs; at this point the object is no longer a ThreadedWrite but a cppthread.
  4. ~cppthread runs and waits for the thread.
  5. The thread calls the callback and because the object now has dynamic type cppthread, cppthread::threadedFunc is called.

It is possible that 5. might happen before 3., in which case you will get the expected output.

If you make sure you wait for the thread to finish at step 3. then it will work fine. Perhaps you could call terminate inside ~ThreadedWrite?

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • c++ 、 pthread 和静态回调。 “this”返回一个指向派生类的基类inctead的指针[重复](c++ , pthread and static callbacks. "this" returns a pointer to the base class inctead of the derived one [duplicate])
    问题 这个问题在这里已经有了答案: c++ 、 pthread 和静态回调。 “this”返回一个指向派生类的基类 inctead 的指针(第 2 部分) (1 个回答) 5年前关闭。 我使用这个 cpp 线程类作为基础。 我将其用作线程的基类。 请注意,在我的情况下 Thread::main() 是一个虚函数(与链接中不同)。 所以我基本上使用: class Thread { public: virtual void main() { cout << "This should not be run once derived and redefined." << endl; } void run() { pthread_create(&thread, 0, &callback, this); } pthread_t thread; }; // class Thread void* callback(void* obj) { static_cast<Thread*>(obj)->main(); return(0); } // callback 然后我创建一个派生类并重新定义myThreadedClass::main()成员以实际做一些有意义的事情。 最后,我从其他类或我的主函数调用实例化 myThreadedClass 对象,如下所示: main(int argc, char**
  • c++ , pthread and static callbacks. "this" returns a pointer to the base class inctead of the derived one [duplicate]
    This question already has an answer here: c++ , pthread and static callbacks. "this" returns a pointer to the base class inctead of the derived one (part 2) (1 answer) Closed 5 years ago. I am using as basis this cpp thread class. This I use as a base class for threads. Note that in my case Thread::main() is a virtual function (unlike in the link). So I basically use: class Thread { public: virtual void main() { cout << "This should not be run once derived and redefined." << endl; } void run() { pthread_create(&thread, 0, &callback, this); } pthread_t thread; }; // class Thread void* callback
  • 强制转换为 void* 以将对象传递给 c++ 中的 pthread(casting to void* to pass objects to pthread in c++)
    问题 我对如何将对象传递给 pthread_create 函数有点困惑。 我发现了很多关于强制转换为 void*、将参数传递给 pthread_create 等的零碎信息,但没有任何内容可以将它们联系在一起。 我只是想确保我已经把所有事情都绑在一起了,没有做任何愚蠢的事情。 假设我有以下线程类: Edit: fixed mis-matched static_cast 。 class ProducerThread { pthread_t thread; pthread_attr_t thread_attr; ProducerThread(const ProducerThread& x); ProducerThread& operator= (const ProducerThread& x); virtual void *thread_routine(void *arg) { ProtectedBuffer<int> *buffer = static_cast<ProtectedBuffer<int> *> arg; int randomdata; while(1) { randomdata = RandomDataGen(); buffer->push_back(randomdata); } pthread_exit(); } public: ProtectedBuffer<int>
  • C ++:路由到成员函数的静态函数包装器?(C++: static function wrapper that routes to member function?)
    问题 我已经尝试了各种设计方法来解决此问题,但似乎似乎做对了。 我需要公开一些静态函数以用作C库的回调函数。 但是,我希望实际的实现是非静态的,因此我可以使用虚函数并在基类中重用代码。 如: class Callbacks { static void MyCallBack() { impl->MyCallBackImpl(); } ... class CallbackImplBase { virtual void MyCallBackImpl() = 0; 但是,我试图解决这一问题(Singleton,通过将Callbacks包含在实现者类中来进行组合等),我最终陷入了死胡同(Impl通常最终指向基类,而不是指向派生类)。 我想知道这是否完全有可能,还是我坚持创建某种辅助函数而不是使用继承? 回答1 用户定义了传递给回调函数的任何参数吗? 有什么方法可以将用户定义的值附加到传递给这些回调的数据上? 我记得当我为Win32窗口实现包装库时,我使用SetWindowLong()将this指针附加到窗口句柄,以后可以在回调函数中检索this指针。 基本上,您需要将this指针包装在某个地方,以便在触发回调时可以检索它。 struct CALLBACKDATA { int field0; int field1; int field2; }; struct MYCALLBACKDATA
  • 是否可以将 bind() *this 绑定到类成员函数以对 C API 进行回调(Is it possible to bind() *this to class member function to make a callback to C API)
    问题 有没有办法使用 boost 或 std bind() 以便我可以在 C API 中使用结果作为回调? 这是我使用的示例代码: #include <boost/function.hpp> #include <boost/bind/bind.hpp> typedef void (*CallbackType)(); void CStyleFunction(CallbackType functionPointer) { functionPointer(); } class Class_w_callback { public: Class_w_callback() { //This would not work CStyleFunction(boost::bind(&Class_w_callback::Callback, this)); } void Callback(){std::cout<<"I got here!\n";}; }; 谢谢! 回答1 不,没有办法做到这一点。 问题在于,C 函数指针从根本上说无非是一个指令地址:“转到这个地址,然后执行找到的指令”。 您想要带入函数的任何状态都必须是全局的,或者作为参数传递。 这就是为什么大多数 C 回调 API 都有一个“上下文”参数,通常是一个空指针,您可以传入该参数,并且仅用于允许您传入所需的数据。 回答2 您不能在可移植 C+
  • C++ 异常是否足以实现线程本地存储?(Are C++ exceptions sufficient to implement thread-local storage?)
    问题 我正在评论线程本地存储很好的答案,并回忆了另一个关于异常的信息性讨论,我认为 throw 块内的执行环境唯一的特殊之处是异常对象被 rethrow 引用。 将两个和两个放在一起,不会在其主函数的函数捕获块内执行整个线程使其具有线程本地存储吗? 它似乎工作正常,尽管很慢。 这是小说还是人物塑造? 有没有其他方法可以解决这个问题? 我最初的前提是否正确? get_thread在您的平台上会产生什么样的开销? 优化的潜力有多大? #include <iostream> #include <pthread.h> using namespace std; struct thlocal { string name; thlocal( string const &n ) : name(n) {} }; struct thread_exception_base { thlocal &th; thread_exception_base( thlocal &in_th ) : th( in_th ) {} thread_exception_base( thread_exception_base const &in ) : th( in.th ) {} }; thlocal &get_thread() throw() { try { throw; } catch( thread_exception
  • C++入门知识点总结——面向对象/高级编程
    C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。 1.面向对象: 类&对象:类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成员。 类的定义:类定义是以关键字class开头,后跟类的名称。 class Box { public: double length; // 盒子的长度 double breadth; // 盒子的宽度 double height; // 盒子的高度 }; 定义类的对象:类提供了对象的蓝图,所以基本上,对象是根据类来创建的。 Box Box1; // 声明 Box1,类型为 Box Box Box2; // 声明 Box2,类型为 Box 访问数据成员:类的对象的公共数据成员可以使用直接成员访问运算符 (.) 来访问。 Box1.height = 5.0; 类的成员函数:类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。 class Box { public: double length; // 长度 double breadth; // 宽度 double height; // 高度 double
  • 类成员中的 pthread_create(pthread_create in member of class)
    问题 假设我有以下课程: * .h : class MyClass{ void caller(); int threadProcuder(void *args); }; * cp : void MyClass::caller() { pthread_t i; pthread_create(&i,NULL,(void*(*)(void*))&MyClass::threadProcedure,(void*)this); } int MyClass::threadProcedure(void *args) { cout << "body of thread" << endl; } 不幸的是,线程没有运行。 回答1 正确的方法是: // Must declare the callback is extern "C" // As you are calling back from a C library. // As this is compiles as C it can only call functions that use the C ABI // There is no guarantee in the C++ standard that static member functions // use the same ABI as a "C" function. // //
  • 虚拟方法 & this 指针(Virtual method & this pointer)
    问题 我刚刚开始学习 C++,我正在尝试制作具有 Java Thread 类基本功能的 Thread 类。 我想要做的是创建一个你子类化的类,编写一个 Run 方法(它在基类中是纯虚拟的)创建一个子类的对象,在它上面调用 start 方法并且你有线程。 问题是,在我使用 C++ 的方式中,调度没有正确完成 - 就像 Run 函数不是虚拟的,基类的 Run 方法被调用。 这是标题的代码 #ifndef _THREAD_H_ #define _THREAD_H_ #include <pthread.h> class Thread { public: Thread(); void Start(); ~Thread(); protected: virtual void Run() = 0; private: static void *RunWrapper(void *); pthread_t thread; }; #endif 实施 #include "thread.h" #include <pthread.h> Thread::Thread() { } void Thread::Start() { pthread_create(&thread, NULL, Thread::RunWrapper, (void *) this); } void *Thread::RunWrapper
  • OpenSSL 和多线程(OpenSSL and multi-threads)
    问题 我一直在阅读有关如果在多线程应用程序中使用 OpenSSL 的要求,您必须向 OpenSSL 注册线程标识函数(以及互斥创建函数)。 在 Linux 上,根据 OpenSSL 提供的示例,通常通过注册这样的函数来识别线程: static unsigned long id_function(void){ return (unsigned long)pthread_self(); } pthread_self() 返回一个 pthread_t,这适用于 Linux,因为 pthread_t 只是 unsigned long 的 typedef。 在 Windows pthreads、FreeBSD 和其他操作系统上,pthread_t 是一个结构体,具有以下结构: struct { void * p; /* Pointer to actual object */ unsigned int x; /* Extra information - reuse count etc */ } 这不能简单地转换为 unsigned long,当我尝试这样做时,它会引发编译错误。 我尝试将 void *p 转换为 unsigned long,理论上内存指针应该在线程间保持一致和唯一,但这只会导致我的程序崩溃很多。 使用 Windows pthreads 或 FreeBSD
  • Virtual method & this pointer
    I'm just beginning to learn C++ and I'm trying to make Thread class that that has the basic functionality of the Java Thread class. What I'm trying to do is make a class which you subclass, write a Run method (which is pure virtual in the base class) create an object of the subclass call the start method on it and you have thread. The problem is that in the way I use C++ the dispatch isn't done correctly - it's like the Run function isn't virtual, the Run method of the base class is called. Here is the code for the header #ifndef _THREAD_H_ #define _THREAD_H_ #include <pthread.h> class Thread
  • 销毁Thread本地存储中的静态类成员(Destruction of static class members in Thread local storage)
    问题 我正在编写一个快速的多线程程序,我想避免同步(需要同步的函数必须每秒调用 5,000,000 次,所以即使是互斥锁也太重了)。 场景是:我有一个类的单个全局实例,每个线程都可以访问它。 为了避免同步,类内的所有数据都以只读方式访问,除了一堆类成员,然后在 TLS 中声明(使用 __thread 或 __declspec(thread))。 不幸的是,为了使用编译器提供的 __thread 接口,类成员必须是静态的并且没有构造函数/解构函数。 我使用的类当然有自定义构造函数,所以我声明,作为类成员,一个指向该类的指针(类似于静态 __thread MyClass* _object)。 然后,线程第一次从全局实例调用方法时,我将执行类似“(if _object == NULL) object = new MyClass(...)”的操作。 我最大的问题是:有没有一种聪明的方法来释放这个分配的内存? 这个全局类来自一个库,被程序中的多个线程使用,每个线程的创建方式不同(即每个线程执行不同的函数),每次都不能放一段代码线程将终止。 感谢大伙们。 回答1 当传递 DLL_THREAD_DETACH 时,TLS 清理通常在 DllMain 中完成。 如果您的代码全部在 EXE 而不是 DLL 中,那么您可以创建一个由 EXE 加载的虚拟 DLL,然后在 DLL_THREAD_DETACH
  • cgo:Go 内存中的 Go 指针(cgo: Go pointers in Go memory)
    问题 代码是否: unsafe.Pointer(&du) 其中du是某个interface满足以下列表中的规则 1? https://github.com/golang/go/issues/12416 Go 代码可以将 Go 指针传递给 C,前提是它指向的 Go 内存不包含任何 Go 指针。 在 C 执行期间必须保留该规则,因为程序不得将任何 Go 指针存储到该内存中。 换句话说,指向 Go interface的 C 指针是否被视为“指向包含 Go 指针的 Go 内存的指针”? 更新: 我的问题是以下代码: type Receiver interface { Signal() } func WowFunction(data []byte, du Receiver) { C.wow_function( (*C.char)( unsafe.Pointer(&data[0]) ), (C.size_t)(len(data)), unsafe.Pointer(&du)) // this is my suspect } 我的想法是让 C 代码调用Receiver的“方法” Signal() 。 我通过导出 Go-callback 并将该&du作为参数传递给回调来实现这一点: //export go_callback func go_callback(object_ptr unsafe
  • 在特定对象实例上调用C ++函数指针(Calling a C++ function pointer on a specific object instance)
    问题 我有一个函数指针,定义为: typedef void (*EventFunction)(int nEvent); 有没有一种方法可以使用C ++对象的特定实例来处理该功能? class A { private: EventFunction handler; public: void SetEvent(EventFunction func) { handler = func; } void EventOne() { handler(1); } }; class B { private: A a; public: B() { a.SetEvent(EventFromA); } // What do I do here? void EventFromA(int nEvent) { // do stuff } }; 编辑: Orion指出了Boost提供的选项,例如: boost::function<int (int)> f; X x; f = std::bind1st( std::mem_fun(&X::foo), &x); f(5); // Call x.foo(5) 不幸的是,Boost不是我的选择。 是否可以使用C ++编写某种“可弯曲”函数,以将指向成员函数的指针包装到普通函数指针中? 回答1 我强烈推荐Don Clugston出色的FastDelegate库。
  • C++ 在类里面使用多线程技术
    有很多时候,我们希望可以在C++类里面对那些比较耗时的函数使用多线程技术,但是,C++类的成员函数的函数指针不能直接做为参数传到pthread_create,主要因为是C++成员函数指针带有类命名空间,同时成员函数末尾是会被C++编译器加上可以接收对象地址的this指针参数。因此需要将成员函数做一定的转化,将其转化为不被编译器加上this指针,而由我们自己来为该函数维护”this”指针即可。 #include <stdio.h> #include <stdlib.h> #include <iostream> #include <time.h> #include <unistd.h> #include <pthread.h> using namespace std; class Test { public: int sum; int cnt; Test(){sum=0;} public: int insert(); void * insert_pth(void*); void lanch(); }; int Test::insert() { sleep(2); sum+=1; } void * Test::insert_pth(void*) { insert(); } void Test::lanch() { pthread_t pth; pthread_create(&pth
  • C ++实现定时回调函数(c++ Implementing Timed Callback function)
    问题 我想用c ++实现一些系统,以便我可以调用一个函数并要求在X毫秒内调用另一个函数。 像这样的东西: callfunctiontimed(25, funcName); 25是应调用该函数之前的毫秒数。 我想知道是否为此需要多线程,然后使用一些延迟功能? 除了使用函数指针之外,类似的功能将如何工作? 回答1 许多人在此问题上都做出了很好的回答,但是我会直接解决这个问题,因为几年前我也遇到过类似的问题。 由于某些原因,我无法使用Boost。我知道Boost在许多开源软件中都有出色的用途。 而且,我真的很想特别了解计时器和回调,因为它们与基于Linux的环境有关。 所以,我写了我自己的。 从根本上讲,我有一个Timer类和一个TimerCallback类。 一个典型的回调,实现为TimerCallback类的继承类,它将在回调时将要执行的操作放在专门针对需要实现的triggered ()方法中。 按照通常的语义, Timer对象与回调对象相关联,该对象可能包含执行回调所需的所有必需信息。 计时器调度由一个环境范围的计时器minheap管理,该计时器必须在单独的线程/进程中维护。 此minheap任务仅做一件事:最小化将来设置的回调事件的最小堆。 Minheap选择下一个要在O(1)触发的事件,并且可以为n计时器事件最小化O(log n)的其余事件。 它还可以在O(log n
  • g++ 错误:pthread_create() 和指向成员函数的指针 [重复](g++ error : pthread_create() and pointer to member function [duplicate])
    问题 这个问题在这里已经有了答案: 8 年前关闭。 可能的重复: 类中的 pthread 函数 我正在尝试创建一个带有启动例程的线程,但是 g++ 不喜欢我的语法。 class myClass { void* myFunction(void* myArg) { // some code, useless here } void start() { pthread_t thread_id; int* fd; //Some code, useless here. pthread_create(&thread_id, 0, &myFunction, (void*) fd); } } 在编译器期间,g++ 告诉我ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&myFunction' ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '
  • 腾讯C++后台开发面试笔试知识点
    gdb调试命令 step和next的区别? 当前line有函数调用的时候,next会直接执行到下一句 ,step会进入函数. 查看内存 (gdb)p &a //打印变量地址 (gdb)x 0xbffff543 //查看内存单元内变量 0xbffff543: 0x12345678 (gdb) x /4xb 0xbffff543 //单字节查看4个内存单元变量的值 0xbffff543: 0x78 0x56 0x34 0x12 多线程调试 (gdb) info threads:查看GDB当前调试的程序的各个线程的相关信息 (gdb) thread threadno:切换当前线程到由threadno指定的线程 break filename:linenum thread all 在所有线程相应行设置断点,注意如果主线程不会执行到该行,并且启动all-stop模式,主线程执行n或s会切换过去 set scheduler-locking off|on\step 默认off,执行s或c其它线程也同步执行。on,只有当前线程执行。step,只有当前线程执行 show scheduler-locking 显示当前模式 thread apply all command 每个线程执行同意命令,如bt。或者thread apply 1 3 bt,即线程1,3执行bt。 查看调用堆栈 (gdb)bt
  • 如何使用 AudioQueue 在 C++ 中为 Mac OSX 播放声音(How to use AudioQueue to play a sound for Mac OSX in C++)
    问题 我试图在 OSX 上从缓冲区播放声音(例如:相当于 Windows 的“PlaySound”功能)。 我已经整理了一些 C++ 代码来使用 AudioQueue 播放音频(因为我认为这是在 OSX 上播放音频的最简单方法)。 但是,不会产生任何声音,也不会调用音频回调函数。 有谁知道我做错了什么,或者有没有人有一个简单的 C/C++ 示例来说明如何在 OSX 上播放声音? #include #include #define BUFFER_COUNT 3 static struct AQPlayerState { AudioStreamBasicDescription desc; AudioQueueRef queue; AudioQueueBufferRef buffers[BUFFER_COUNT]; unsigned buffer_size; } state; static void audio_callback (void *aux, AudioQueueRef aq, AudioQueueBufferRef bufout) { printf("I never get called!\n"); #define nsamples 4096 short data[nsamples]; for (int i=0;imAudioDataByteSize = nsamples *
  • 面试总结:鹅厂Linux后台开发面试笔试C++知识点参考笔记
    微信搜「后端技术学堂」有干货,本文已收录于Github:https://github.com/imcoderlemon/CodeClass 内含原创干货文章,千本计算机电子书,3本LeetCode题解,各类编程资源 文章是由自己笔试面试腾讯的笔记整理而来,整理的时候又回顾了一遍,中间工作忙断断续续整理了半个月,才完成现在的样子。主要是针对面试的C++后台开发岗位,涵盖了大部分C++相关的可能会被问到的技术点,作为面试技术的参考回头查阅。 文末提供了本文知识点学习资源获取方式,需要的同学自取。 这篇笔记是基础C++知识点总结,没有过多的阐述后台开发的系统架构和分布式后台服务设计相关,还有c++11新特性,这些笔试面试也会被问到但不在这篇讨论范围,可以关注专栏后面如果有机会再补上。 为什么析构函数要是虚函数? 基类指针可以指向派生类的对象(多态性),如果删除该指针delete []p;就会调用该指针指向的派生类析构函数,而派生类的析构函数又自动调用基类的析构函数,这样整个派生类的对象完全被释放。如果析构函数不被声明成虚函数,则编译器实施静态绑定,在删除基类指针时,只会调用基类的析构函数而不调用派生类析构函数,这样就会造成派生类对象析构不完全。所以,将析构函数声明为虚函数是十分必要的。 gdb调试命令 step和next的区别? 当前line有函数调用的时候,next会直接执行到下一句