异步方式调用,携带指针过去,回调如果没有返回来,之后内存怎么删除

wintree 2014-03-20 07:49:12
异步方式调用,携带指针过去,回调如果没有返回来,之后内存怎么删除,求各位大神是否有这样的问题

因为我搞的系统是 全部异步方式的使用。。。。
...全文
467 42 打赏 收藏 转发到动态 举报
写回复
用AI写文章
42 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2014-03-24
  • 打赏
  • 举报
回复
搜“内存池”
「已注销」 2014-03-24
  • 打赏
  • 举报
回复
智能指针用的啥库呢?那个是不是多线程安全呢,同时操作引用计数有木有问题呢? 我做网络数据的时候,上层数据过来往下发,给下层设置一个回调,等待回调里面设置同步标志有时候会卡死。 如果用智能指针,下层是硬件系统厂商的tcpip跟硬件网卡驱动,他们又不会主动去修改引用计数器,所以在封包修改的时候总是有那么个问题解决不了。 愁啊愁。。。。。
「已注销」 2014-03-24
  • 打赏
  • 举报
回复
智能指针用的啥库呢?那个是不是多线程安全呢,同时操作应用技术有木有问题呢? 我做网络数据的时候,上层数据过来往下发,给下层设置一个回调,等待回调里面设置同步标准有时候会卡死。 如果用智能指针,下层是硬件系统厂商的tcpip跟硬件网卡驱动,他们又不会主动去修改应用计数器,所以在封包修改的时候总是有那么个问题解决不了。 愁啊愁。。。。。
版主大哥 2014-03-24
  • 打赏
  • 举报
回复
一个方法是使用引用计数方式,即智能指针 还一个是传指针的时候使用指针的指针,或者指针引用,这样就是不同线程操作该指针,都是一个。
qq120848369 2014-03-24
  • 打赏
  • 举报
回复
引用 39 楼 jha334201553 的回复:
智能指针用的啥库呢?那个是不是多线程安全呢,同时操作应用技术有木有问题呢? 我做网络数据的时候,上层数据过来往下发,给下层设置一个回调,等待回调里面设置同步标准有时候会卡死。 如果用智能指针,下层是硬件系统厂商的tcpip跟硬件网卡驱动,他们又不会主动去修改应用计数器,所以在封包修改的时候总是有那么个问题解决不了。 愁啊愁。。。。。
智能指针的引用计数是线程安全的, 但不要勿用。
zhcosin 2014-03-22
  • 打赏
  • 举报
回复
你没有超时机制啊?请求之前启个定时器,如果收到响应则停止定时器,否则定时器到期自成生成一个超时的响应。
Liekkas 2014-03-21
  • 打赏
  • 举报
回复
在回调函数捕获异常的地方,把指针给释放了
wintree 2014-03-21
  • 打赏
  • 举报
回复
我是在压测出现的问题搞不懂来问啊,多谢你指导。。。。
引用 31 楼 mougaidong 的回复:
我做过相关实验,出问题的时候也会调用。 真不明白,代码都有了,你为什么不稍微花点时间实践一下,而是来这里问。 问就问,别人回答了,你又要怀疑。 [quote=引用 29 楼 wallwind 的回复:] 和你写的一样, 主动调用executeCommand ,回调函数是redisCallbackFunc 和你的差不多,能确定一定会回调? [quote=引用 28 楼 mougaidong 的回复:] 没看明白,楼主到底想问什么。 [quote=引用 27 楼 wallwind 的回复:] [quote=引用 25 楼 mougaidong 的回复:] 给你个例子。 特别声明重要的一点,只要这个模块所在的进程本身没问题,不管什么情况(例如:断网)发生,这个callback都会被调用。
void CallbackExample(redisAsyncContext* ac, void* reply, void* privdata) {
  std::unique_ptr<YourType> key_delta(reinterpret_cast<YourType*>(privdata));
  redisReply* r = reinterpret_cast<redisReply*>(reply);
  if (r->type == REDIS_REPLY_ERROR) {
    LOG(ERROR) << "something...";
    return;                                                                                                                                                                                                                                                                   
  }

  DoSomethingWithReply(r);
}
void TaskRedisClient::redisCallbackFunc(redisAsyncContext *c, void *r, void *privdata)
{
	redisReply *reply = (redisReply *)r;
	Task *task = (Task *)privdata;
	if (reply == NULL )
	{
		log(Error, " RedisClient::asyncCallbackFunc fail,%s", (char*)privdata);
		SAFE_DELETE_PTR(task)
		return;
	}
	if (REDIS_REPLY_ERROR == reply->type)
	{
		log(Error, "RedisClient::asyncCallbackFunc error:%s,%s", reply->str, (char*)privdata );
		SAFE_DELETE_PTR(task)
		return;
	}
这个是我写的。。。
bool TaskRedisClient::executeCommand(const string& cmd,void *privdata)
{
	if (NULL == redis_context)
	{
		return false;
	}
	if( REDIS_OK != redisAsyncCommand(redis_context, redisCallbackFunc, privdata, cmd.c_str()) )
	{
		return false;
	}
	return true;
}
这边是我写的。。。。回调函数,redis这个回调函数确定回会 回调成功么?[/quote][/quote][/quote][/quote]
qq120848369 2014-03-21
  • 打赏
  • 举报
回复
异步设计中,生命期取决于最后一个释放的人,人无法获知谁最后一个的情况下,只能使用智能指针解决,closure也是因为带着智能指针走的。
turing-complete 2014-03-21
  • 打赏
  • 举报
回复
我做过相关实验,出问题的时候也会调用。 真不明白,代码都有了,你为什么不稍微花点时间实践一下,而是来这里问。 问就问,别人回答了,你又要怀疑。
引用 29 楼 wallwind 的回复:
和你写的一样, 主动调用executeCommand ,回调函数是redisCallbackFunc 和你的差不多,能确定一定会回调? [quote=引用 28 楼 mougaidong 的回复:] 没看明白,楼主到底想问什么。 [quote=引用 27 楼 wallwind 的回复:] [quote=引用 25 楼 mougaidong 的回复:] 给你个例子。 特别声明重要的一点,只要这个模块所在的进程本身没问题,不管什么情况(例如:断网)发生,这个callback都会被调用。
void CallbackExample(redisAsyncContext* ac, void* reply, void* privdata) {
  std::unique_ptr<YourType> key_delta(reinterpret_cast<YourType*>(privdata));
  redisReply* r = reinterpret_cast<redisReply*>(reply);
  if (r->type == REDIS_REPLY_ERROR) {
    LOG(ERROR) << "something...";
    return;                                                                                                                                                                                                                                                                   
  }

  DoSomethingWithReply(r);
}
void TaskRedisClient::redisCallbackFunc(redisAsyncContext *c, void *r, void *privdata)
{
	redisReply *reply = (redisReply *)r;
	Task *task = (Task *)privdata;
	if (reply == NULL )
	{
		log(Error, " RedisClient::asyncCallbackFunc fail,%s", (char*)privdata);
		SAFE_DELETE_PTR(task)
		return;
	}
	if (REDIS_REPLY_ERROR == reply->type)
	{
		log(Error, "RedisClient::asyncCallbackFunc error:%s,%s", reply->str, (char*)privdata );
		SAFE_DELETE_PTR(task)
		return;
	}
这个是我写的。。。
bool TaskRedisClient::executeCommand(const string& cmd,void *privdata)
{
	if (NULL == redis_context)
	{
		return false;
	}
	if( REDIS_OK != redisAsyncCommand(redis_context, redisCallbackFunc, privdata, cmd.c_str()) )
	{
		return false;
	}
	return true;
}
这边是我写的。。。。回调函数,redis这个回调函数确定回会 回调成功么?[/quote][/quote][/quote]
mujiok2003 2014-03-21
  • 打赏
  • 举报
回复
引用 26 楼 wallwind 的回复:
[quote=引用 23 楼 mujiok2003 的回复:] [quote=引用 22 楼 wallwind 的回复:] [quote=引用 18 楼 mujiok2003 的回复:]
异步方式调用,携带指针过去,回调如果没有返回来
发了两个异步请求,其中一个完成后调用callback,你如何分辨是哪个请求完成了?你只要能分辨是哪个请求,就可以删除对应的资源。如果不能分辨,你的异步设计肯定有问题。
通过传过去的指针。继承了task父类的指针。。。分辨是哪个请求。。。[/quote] 不同的请求用不同的task?[/quote] 对的。 struct sonTask :public Task{}; 根据子类来确定是哪个请求了。。而且task本身是具有唯一标示的。比如id等。[/quote] 有标识符,那就可以在id和对应资源之间建立关系,你要释放,要复用都可以.
wintree 2014-03-21
  • 打赏
  • 举报
回复
和你写的一样, 主动调用executeCommand ,回调函数是redisCallbackFunc 和你的差不多,能确定一定会回调?
引用 28 楼 mougaidong 的回复:
没看明白,楼主到底想问什么。 [quote=引用 27 楼 wallwind 的回复:] [quote=引用 25 楼 mougaidong 的回复:] 给你个例子。 特别声明重要的一点,只要这个模块所在的进程本身没问题,不管什么情况(例如:断网)发生,这个callback都会被调用。
void CallbackExample(redisAsyncContext* ac, void* reply, void* privdata) {
  std::unique_ptr<YourType> key_delta(reinterpret_cast<YourType*>(privdata));
  redisReply* r = reinterpret_cast<redisReply*>(reply);
  if (r->type == REDIS_REPLY_ERROR) {
    LOG(ERROR) << "something...";
    return;                                                                                                                                                                                                                                                                   
  }

  DoSomethingWithReply(r);
}
void TaskRedisClient::redisCallbackFunc(redisAsyncContext *c, void *r, void *privdata)
{
	redisReply *reply = (redisReply *)r;
	Task *task = (Task *)privdata;
	if (reply == NULL )
	{
		log(Error, " RedisClient::asyncCallbackFunc fail,%s", (char*)privdata);
		SAFE_DELETE_PTR(task)
		return;
	}
	if (REDIS_REPLY_ERROR == reply->type)
	{
		log(Error, "RedisClient::asyncCallbackFunc error:%s,%s", reply->str, (char*)privdata );
		SAFE_DELETE_PTR(task)
		return;
	}
这个是我写的。。。
bool TaskRedisClient::executeCommand(const string& cmd,void *privdata)
{
	if (NULL == redis_context)
	{
		return false;
	}
	if( REDIS_OK != redisAsyncCommand(redis_context, redisCallbackFunc, privdata, cmd.c_str()) )
	{
		return false;
	}
	return true;
}
这边是我写的。。。。回调函数,redis这个回调函数确定回会 回调成功么?[/quote][/quote]
turing-complete 2014-03-21
  • 打赏
  • 举报
回复
没看明白,楼主到底想问什么。
引用 27 楼 wallwind 的回复:
[quote=引用 25 楼 mougaidong 的回复:] 给你个例子。 特别声明重要的一点,只要这个模块所在的进程本身没问题,不管什么情况(例如:断网)发生,这个callback都会被调用。
void CallbackExample(redisAsyncContext* ac, void* reply, void* privdata) {
  std::unique_ptr<YourType> key_delta(reinterpret_cast<YourType*>(privdata));
  redisReply* r = reinterpret_cast<redisReply*>(reply);
  if (r->type == REDIS_REPLY_ERROR) {
    LOG(ERROR) << "something...";
    return;                                                                                                                                                                                                                                                                   
  }

  DoSomethingWithReply(r);
}
void TaskRedisClient::redisCallbackFunc(redisAsyncContext *c, void *r, void *privdata)
{
	redisReply *reply = (redisReply *)r;
	Task *task = (Task *)privdata;
	if (reply == NULL )
	{
		log(Error, " RedisClient::asyncCallbackFunc fail,%s", (char*)privdata);
		SAFE_DELETE_PTR(task)
		return;
	}
	if (REDIS_REPLY_ERROR == reply->type)
	{
		log(Error, "RedisClient::asyncCallbackFunc error:%s,%s", reply->str, (char*)privdata );
		SAFE_DELETE_PTR(task)
		return;
	}
这个是我写的。。。
bool TaskRedisClient::executeCommand(const string& cmd,void *privdata)
{
	if (NULL == redis_context)
	{
		return false;
	}
	if( REDIS_OK != redisAsyncCommand(redis_context, redisCallbackFunc, privdata, cmd.c_str()) )
	{
		return false;
	}
	return true;
}
这边是我写的。。。。回调函数,redis这个回调函数确定回会 回调成功么?[/quote]
wintree 2014-03-21
  • 打赏
  • 举报
回复
引用 25 楼 mougaidong 的回复:
给你个例子。 特别声明重要的一点,只要这个模块所在的进程本身没问题,不管什么情况(例如:断网)发生,这个callback都会被调用。
void CallbackExample(redisAsyncContext* ac, void* reply, void* privdata) {
  std::unique_ptr<YourType> key_delta(reinterpret_cast<YourType*>(privdata));
  redisReply* r = reinterpret_cast<redisReply*>(reply);
  if (r->type == REDIS_REPLY_ERROR) {
    LOG(ERROR) << "something...";
    return;                                                                                                                                                                                                                                                                   
  }

  DoSomethingWithReply(r);
}
void TaskRedisClient::redisCallbackFunc(redisAsyncContext *c, void *r, void *privdata)
{
	redisReply *reply = (redisReply *)r;
	Task *task = (Task *)privdata;
	if (reply == NULL )
	{
		log(Error, " RedisClient::asyncCallbackFunc fail,%s", (char*)privdata);
		SAFE_DELETE_PTR(task)
		return;
	}
	if (REDIS_REPLY_ERROR == reply->type)
	{
		log(Error, "RedisClient::asyncCallbackFunc error:%s,%s", reply->str, (char*)privdata );
		SAFE_DELETE_PTR(task)
		return;
	}
这个是我写的。。。
bool TaskRedisClient::executeCommand(const string& cmd,void *privdata)
{
	if (NULL == redis_context)
	{
		return false;
	}
	if( REDIS_OK != redisAsyncCommand(redis_context, redisCallbackFunc, privdata, cmd.c_str()) )
	{
		return false;
	}
	return true;
}
这边是我写的。。。。回调函数,redis这个回调函数确定回会 回调成功么?
wintree 2014-03-21
  • 打赏
  • 举报
回复
引用 23 楼 mujiok2003 的回复:
[quote=引用 22 楼 wallwind 的回复:] [quote=引用 18 楼 mujiok2003 的回复:]
异步方式调用,携带指针过去,回调如果没有返回来
发了两个异步请求,其中一个完成后调用callback,你如何分辨是哪个请求完成了?你只要能分辨是哪个请求,就可以删除对应的资源。如果不能分辨,你的异步设计肯定有问题。
通过传过去的指针。继承了task父类的指针。。。分辨是哪个请求。。。[/quote] 不同的请求用不同的task?[/quote] 对的。 struct sonTask :public Task{}; 根据子类来确定是哪个请求了。。而且task本身是具有唯一标示的。比如id等。
turing-complete 2014-03-21
  • 打赏
  • 举报
回复
给你个例子。 特别声明重要的一点,只要这个模块所在的进程本身没问题,不管什么情况(例如:断网)发生,这个callback都会被调用。
void CallbackExample(redisAsyncContext* ac, void* reply, void* privdata) {
  std::unique_ptr<YourType> key_delta(reinterpret_cast<YourType*>(privdata));
  redisReply* r = reinterpret_cast<redisReply*>(reply);
  if (r->type == REDIS_REPLY_ERROR) {
    LOG(ERROR) << "something...";
    return;                                                                                                                                                                                                                                                                   
  }

  DoSomethingWithReply(r);
}
lucifer886 2014-03-21
  • 打赏
  • 举报
回复
引用 11 楼 wallwind 的回复:
[quote=引用 3 楼 mougaidong 的回复:] 异步系统,不管调用成功与否,都应当给执行callback的机会。 失败的时候,可以有专门的callback。 也可以在callback的签名中加入状态码参数,让编写callback的人自己去判断成功与否,进而做出相应的逻辑。 所以,如果说你用的系统失败了就不执行callback,那么这个系统是不完备的,问题不在你这边。
我主要是怕 我调用了函数之后,通过网络发包回去,然后,网络断了,回不了包了。。。就会导致内存泄露。。。[/quote] 这个跟智能指针无关吧,你要设置个超时的,发送超时的话就删了。
mujiok2003 2014-03-21
  • 打赏
  • 举报
回复
引用 22 楼 wallwind 的回复:
[quote=引用 18 楼 mujiok2003 的回复:]
异步方式调用,携带指针过去,回调如果没有返回来
发了两个异步请求,其中一个完成后调用callback,你如何分辨是哪个请求完成了?你只要能分辨是哪个请求,就可以删除对应的资源。如果不能分辨,你的异步设计肯定有问题。
通过传过去的指针。继承了task父类的指针。。。分辨是哪个请求。。。[/quote] 不同的请求用不同的task?
wintree 2014-03-21
  • 打赏
  • 举报
回复
引用 18 楼 mujiok2003 的回复:
异步方式调用,携带指针过去,回调如果没有返回来
发了两个异步请求,其中一个完成后调用callback,你如何分辨是哪个请求完成了?你只要能分辨是哪个请求,就可以删除对应的资源。如果不能分辨,你的异步设计肯定有问题。
通过传过去的指针。继承了task父类的指针。。。分辨是哪个请求。。。
wintree 2014-03-21
  • 打赏
  • 举报
回复
引用 20 楼 mougaidong 的回复:
就redis而言吧,你用的是hiredis客户端吗? [quote=引用 15 楼 wallwind 的回复:] [quote=引用 14 楼 mougaidong 的回复:] 你需要确保的是,无论什么事情发生callback都会被执行。 所以,问题的根源不在于你贴出的代码上,而是明确一下callback在什么情况下会调用。 [quote=引用 13 楼 wallwind 的回复:] [quote=引用 12 楼 mougaidong 的回复:] 你可能还不明白我的意思,断网了也是错误的一种,callback照样会执行,怎么会泄漏呢? 再说了,这个场景不就是典型的timeout嘛,你设置一个timeout的callback啊。 [quote=引用 11 楼 wallwind 的回复:] [quote=引用 3 楼 mougaidong 的回复:] 异步系统,不管调用成功与否,都应当给执行callback的机会。 失败的时候,可以有专门的callback。 也可以在callback的签名中加入状态码参数,让编写callback的人自己去判断成功与否,进而做出相应的逻辑。 所以,如果说你用的系统失败了就不执行callback,那么这个系统是不完备的,问题不在你这边。
我主要是怕 我调用了函数之后,通过网络发包回去,然后,网络断了,回不了包了。。。就会导致内存泄露。。。[/quote] [/quote] struct Task { int status; void run(); } Task *pstTask=new Task(); //主动调用的函数 void send_func(Task* pstTask) { // 痛过socket发送到对端系统 } //回调的函数 void callback(Task* pstTask) { pstTask->run(); //执行完删除 delete pstTask; }[/quote][/quote] 我的系统里有redis 的异步回调函数,还有thrift 的异步回调函数。。。[/quote][/quote] 对的,用hiredis的一些异步接口,封装了一下。。。。异步回调的一个客户端。。。
加载更多回复(22)

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧