我自己已经解决了这个问题,并且不会给予赏金.该问题是由非GUI线程启动的GUI操作引起的.
Qt 4.7 OSX 10.6.8
应用程序中有很多代码,但并没有涉及到正在发生的事情.
数据内存泄漏发生在单个连接的上下文中,该连接在单个Qt线程内打开,读取,写入和关闭.我正在使用固定内存对象(pMsg)来保存我的消息,然后将它们发送到外部设备,如下所示:
m_pTcpSocket->write((char*)pMsg->Buf8, (qint64)pMsg->GetLength());
Run Code Online (Sandbox Code Playgroud)
Buf8是一个2048字节的静态数组.GetLength是消息的前16位并且是针对0xFF的,因此是0到255之间的数字.对于这些消息应该返回4,总是在我的诊断中.这两个操作都被它们自己的互斥锁(意思是不同的互斥锁)所包围.消息长度通常是4个字节.这些消息可靠地到达有线局域网其他地方的接收设备; 当它们到达时它们是正确的,并且设备适当地响应仅针对那些消息的ACK.之后我尝试添加一个flush()调用; 没有帮助(也不应该有任何冲洗,但是......)我不知道泄漏是在write()中.
依次发送这些消息会导致我从设备收到ACK消息.我这样看了:
if (m_pTcpSocket->waitForReadyRead(100))
{
while ((bytesavailable = m_pTcpSocket->bytesAvailable()))
{
m_pTcpSocket->read(RBuf, bytesavailable);
AssembleMsg(Buf, bytesavailable); // state machine empties Buf
}
}
Run Code Online (Sandbox Code Playgroud)
在循环之后,bytesavailable为零(当然.)Buf是一个无符号字符指针,指向2048个无符号字符的静态数组,在接收到每个数据部分之后,我运行一个组装消息的简单状态机.消息长度为4.按预期接收和组合消息,不进行内存分配,也不声明对象.这两个操作都被它们自己的互斥锁包围(意思是不同的互斥锁,因此它们不能在rx和tx之间进行交互.)一旦组合了消息,它所做的就是重置一个计数器,将延迟设置为下一个keepalive消息(这是如果没有它们,设备将断开连接.)延迟是通过在waitforreadyread(100)之后计数累积的,只要设备不向该端口发送任何内容,就会计算该长度的间隔,这是典型的行为.这样,不需要计时器.时机运行正常.消息一到达就会被读取,或者至少在100毫秒内被读取.他们不积累.所以我认为读取缓冲区不会变得很大(呃).但是......我不知道.有些东西越来越大了!
这就是阅读.但我不知道泄漏是在read()中.
但它必须是一个或另一个.如果我不发送这些消息(这意味着我也没有收到ACK消息),那么就没有泄漏.应用程序中的任何地方都没有其他任 这是它启动的模式,没有其他活动正在进行,我只是保持连接打开,所以当运行无线电时,端口已准备就绪.
这两个都在同一个线程中运行,它们都运行在同一个套接字上.线程连续运行,同一个套接字保持打开状态(实际上是几个小时).所以这不是套接字对象删除问题.
某些品牌的SDR收音机问题更加严重,因为它们在接收操作期间需要保持活动状态,这意味着应用程序坐在那里并且在接收时就像疯狂一样咀嚼内存,就像它坐在那里等待着去一样.
我在大约12小时内丢失了大约250兆字节,大约在10万以下.我可以看到应用程序内存每次增加1 mb,大约每秒一次.
我已经广泛搜索了,我所能找到的所有内容都是无法通过多个连接删除tcp对象,这绝对不是问题所在.
我真的很茫然.问题与我在线程中使用套接字有关吗?应用程序(一个非常复杂的软件定义的无线电应用程序)可以运行10到16个线程,具体取决于它正在做什么; 我在他们自己的线程中运行数据传输,这样它们就不会被绑定主事件循环的任何东西所破坏.
我已经尝试了valgrind,但它在尝试启动它之后终止了应用程序,在此任何一个开始之前.我不认为它喜欢线程或其他东西.或者它可能是10.6.8,但无论如何,它不起作用.Qt 4.7无论如何都没有集成它.我知道无法从应用程序中跟踪内存使用情况,以便我可以包装每个发送和接收,并至少找出哪一个(或两个?)负责.
***编辑:通过改变keepalive消息的速率,我直接改变了内存泄漏的速度,正如我上面所说,如果没有发送keepalive,根本就没有内存丢失.
这就是我能想到的全部告诉你们的人; 任何建议都是受欢迎的,任何关于Qt中TCP怪癖的启示都会受到欢迎,基本上是任何事情.我已经花了很多天这个时间,我只是在这个关键时刻.
我有一个应用程序,软件定义无线电,在一个端口上广播UDP数据包,告诉听众已经设置了什么频率和解调模式(等等).
我编写了一个演示python客户端(下面的代码)来监听端口,并将相应数据包中的信息转储到控制台.
这些都在OSX 10.6,Snow Leopard下运行.他们在那里工作.
我的问题是:Python应用程序必须在无线电应用程序之前启动,或者在绑定期间声称端口已在使用(ERRNO 47),我不明白为什么.无线电应用正在广播UDP; 当然,我想容纳多个听众 - 这就是广播的想法,或者至少,所以我想.
所以这里是Python代码(由于堆栈溢出真的很愚蠢"make-it-code"缩进,缩进有点混乱,但我保证你没关系):
#!/usr/bin/python
import select, socket
# AA7AS - for SdrDx UDP broadcast
# this is a sample python script that captures the UDP messages
# that are coming from SdrDx. SdrDx tells you what frequency and
# mode it has been set to. This, in turn, would be used to tell
# another radio to tune to that frequency and mode.
# UDP packet from SdrDx is zero terminated, but …Run Code Online (Sandbox Code Playgroud) 环境
问题
从OS X 10.6.8到OS X 10.11,工具提示和QComboBox弹出菜单行为都很好.
在10.12下,QComboBox弹出菜单的工具提示和弹出功能是空白的.
工具提示是空白的黄色表,背景看起来正确,但没有文字.我在Qt Designer 2中设置工具提示内容; 没有什么花哨的.在每种情况下,它只是香草文本.
QComboBox弹出菜单缺少文本和复选标记.当弹出窗口关闭时,窗口小部件只显示一行,所选项目确实显示.您也可以指向它,滚动鼠标滚轮,项目按预期更改.它只是弹出的项目列表是空白的.
对于QComboBox弹出菜单,这是一个有问题的使用示例:
int index;
ui->fftSizecomboBox->addItem("2048 pts", 2048);
ui->fftSizecomboBox->addItem("4096 pts", 2048 * 2);
ui->fftSizecomboBox->addItem("8192 pts", 2048 * 4);
ui->fftSizecomboBox->addItem("16384 pts", 2048 * 8);
ui->fftSizecomboBox->addItem("32768 pts", 2048 * 16);
ui->fftSizecomboBox->addItem("64K pts", 2048 * 32);
ui->fftSizecomboBox->addItem("128K pts", 2048 * 64);
ui->fftSizecomboBox->addItem("256K pts", 2048 * 128);
ui->fftSizecomboBox->addItem("512K pts", 2048 * 256);
ui->fftSizecomboBox->addItem("1M pts", 2048 * 512);
ui->fftSizecomboBox->addItem("2M pts", 2048 * 1024); …Run Code Online (Sandbox Code Playgroud) 根据Qt 4.7.1,Qt Creator 2.1.0,OS X 10.6.8:
我在主窗口ui中有一个QLabel,它使用Courier New/13,可以容纳四行文本.
我创建了四行文本,比一般格式的标签水平短得多:
"我的文字\ r \n"
我在发送之前过滤了文本.cstring中唯一的字符将是0x0D,0x0A,0x20(空格),从那里到小写z(0x7A'),当然还有终止零.没有其他控制字符 - 如果从源接收它们,我用'*'替换它们
我将四行文本作为单个零终止的cstring发送到QLabel setText()
我有时这样做在相当高的速度,几次第二至少 - 这是从FM电台RDBS数据,以便在实时的变化:
qDebug() << rbl; // data keeps coming to console
ui->fourLineLabel->setText(rbl); // add this, display soon stops updating
Run Code Online (Sandbox Code Playgroud)
这有效.一阵子.然后显示停止更新.这是有争议的领域:
4行QLabel http://fyngyrz.com/images/RDSarea.png
如果我把其他所有内容都删除了setText(),那么就不会出现问题.
我知道,对于某些事情,Qt希望在绘画事件中完成绘画.这也是真的setText()吗?
阅读关于qt小部件的文档,它说小部件在他们自己的绘画事件中做自己的绘画......但是这里的行为非常类似于当一个人真正试图在油漆之外使用画家时所发生的那种事件.它肯定与那个有关setText(),所以......嘟..
写此,应用程序已运行了好几个小时,没有任何显示锁止,通过qDebug输出相同的文本到控制台().如果我取消注释setText(),则问题大约需要5分钟.它是100%可重复的.
有什么我应该做的,我不是在做,油漆方面或类似的?
谢谢你的帮助.
我有一些数据的 UDP 广播。我可以在 OSX 10.6.8 下的 python 2.6.1 中打开以下客户端,并且可以正常工作。我可以捕捉数据,一切都很好。
但是:这段代码“消耗”了端口,因为我无法打开另一个端口,第二次尝试绑定失败......我必须允许多个侦听器。这是打开端口的代码:
import select, socket
port = 58083 # port msg is broadcast upon
# Create listening port
# ---------------------
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.bind(('', port))
except:
print 'failure to bind'
s.close()
raise
s.setblocking(0)
Run Code Online (Sandbox Code Playgroud)
...由于 UDP旨在向多个客户端广播(除其他外),我认为我做错了什么。我就是想不通是什么。
我在 activestate 上找到了一个示例,该示例建议:
s.bind(('<broadcast>',port))
Run Code Online (Sandbox Code Playgroud)
...但每次都失败了。绑定到0.0.0.0作品,但也遭受“一个客户端”的问题。绑定到本地 IP(例如192.168.1.100)根本不起作用。删除绑定根本不起作用。
任何人?
我有一个数据库访问模块,我用查询或命令调用.它弄清楚如何处理数据库,并尝试这样做.但是,例如,如果查询或命令字符串是病态的,则对底层PGDB模块的调用可能会引发异常.
PGDB(来自PostgreSQL)返回了一些非常有用的信息,特别是调用了查询或命令中发现的错误.PGDB各种函数的这种用法检索该信息:
try:
pgdb.dothing(mod.withx)
except Exception, e:
mod.error = 'pgdb.dothing('+str(type(mod.withx))+str(mod.withx)+') failed with: '+str(e)
Run Code Online (Sandbox Code Playgroud)
然后当类返回失败时,对象包含.error和viola中的消息,我可以在查询或命令中修复我的愚蠢.
这一切似乎都运行得很好 - (在Python 2.2.2中,有一天可能会变为2.更高......但现在不是 - 而且永远不会变为3.whatever)
但是...我发现混浊的这一位:" 异常不必须继承自Exception因此纯'除了:’.捕获所有异常,不仅系统的字符串例外是没有例外的一个例子继承自Exception "
所以这就是问题:我为什么关心?如果抛出异常,我想知道原因.我不在乎它来自哪里,真的,我只是想要错误消息,我确定不希望Python崩溃.这将包括如果错误来自字符串的东西或其他什么.所以除了捕捉一切都很好.或者它应该是.
是否Exception的参数意味着,如果它来自,例如,String内部,我将不会捕获错误?那么,代码会因未捕获的异常而停止吗?然后我需要针对"不从异常继承"的每种类型获取一系列捕获以获得我想要的行为?像这样的东西:
try:
pgdb.dothing(mod.withx)
except Exception, e:
mod.error = 'pgdb.dothing('+str(type(mod.withx))+str(mod.withx)+') failed with: '+str(e)
except:
mod.error = 'pgdb.dothing('+str(type(mod.withx))+str(mod.withx)+') failed with: WTF???'
Run Code Online (Sandbox Code Playgroud)
...因为那真的......有点糟透了.
而且,如果是这种情况,是否有其他方法可以捕获所有类型的所有异常并为它们获取错误消息?看起来这将是一个高度,非常可取的东西(而且它似乎也应该解决它,它应该看起来有点像前一个例子,而不是后者.)
请回答:是的,我知道Python 2.2.2已经过时了.不,它不会很快升级.这是一个拥有数百万行代码的生产系统; 它是稳定的,我们希望它保持这种方式,基于"没有破坏,没有修复".
我只需要充分理解这部分异常过程打败了我.所有的解释似乎都在假设我所知道的......乐观.:)
感谢您的任何见解.
我有一些(实际上很多)表格数据。在 HTML 3.2 中,我使用 HTML FONT 标记为表格单元格中的文本着色(有时在一个单元格中使用多种颜色)并且它工作正常。
在严格的 HTML 4.01 下,我不能(不应该)使用 FONT,因为它不再受支持。应该使用CSS,对吧?但是,我不能将 CSS 用于表格单元格,因为我必须考虑多种颜色。
所以我有一些跨度,例如这里是黑色的黄色......
<span style="text-color: #ffff00; background-color: #000000;">text-to-color</span>
Run Code Online (Sandbox Code Playgroud)
但是,文本与页面的文本和背景颜色一起显示。不是跨度中的颜色。这在 Firefox 和 Safari 中是正确的。
HTML 验证器说我没有犯任何可怕的错误。
我糊涂了。或者也许困惑。
我在这里缺少什么?
我读到了包装器函数,它将cmp样式比较转换为Python 3中的键样式比较,其中删除了cmp功能.
我有一点时间围绕Python3直键样式sorted()函数的方式,至少据我所知,只有一个为键指定的项目,可以让你正确比较,例如,两个IP用于订购.或火腿电话.
而对于cmp,它没有任何东西:sorted()和sort()用两个ips调用你,你查看了相应的部分,完成了你的决定.
def ipCompare(dqA,dqB):
...
ipList = sorted(ipList,cmp=ipCompare)
Run Code Online (Sandbox Code Playgroud)
火腿无线电呼叫也是如此.排序不是字母; 电话通常是字母+数字+字母; 第一个排序优先级是数字部分,然后是第一个字母,然后是最后一个字母(s.)
使用cmp ......没有汗水.
def callCompare(callA,callB):
...
hamlist = sorted(hamlist,cmp=callCompare)
Run Code Online (Sandbox Code Playgroud)
使用Python3 ...没有经过包装器的箍跳......并且通过了一个项目......我想......怎么能这样做?
如果绝对需要包装器...那么为什么首先在Python3中删除cmp?
我确定我错过了什么.我只是看不到它.:/
好的,现在我知道我错过了什么.解决方案IPs在下面的答案中给出.这是我提出的用于排序公共前缀,区域,后缀形式的火焰调用的密钥:
import re
def callKey(txtCall):
l = re.split('([0-9]*)',txtCall.upper(),1)
return l[1],l[0],l[2]
hamList = ['N4EJI','W1AW','AA7AS','na1a']
sortedHamList = sorted(hamList,key=callKey)
Run Code Online (Sandbox Code Playgroud)
sortedHamList 结果是 ['na1a','W1AW','N4EJI','AA7AS']
详情:
AA7AS出来的callKey()作为7,AA,ASN4EJI出来的callKey()作为4,N,EJIW1AW出来的callKey()作为1,W,AWna1a出来的callKey()作为1,NA,A我有一个相当简单的情况:我在一个线程中有一个高速数据生成器,它生成一个带有[变长]元素的缓冲区.填充此缓冲区后,我有一个将其写入磁盘的使用者.
现在,生成器线程需要返回生成ASAP,如果缓冲区尚未被消费者线程写入,则会旋转到位:
int volatile datatogo=0; // global with starting condition
while(datatogo != 0) // spin, buffer not yet written out
{
if (recflag == 0) return; // recording is terminated
}
// clipped code fills buffer, then:
datatogo = lengthoffill;
Run Code Online (Sandbox Code Playgroud)
...在另一个线程中,缓冲区编写器执行此操作:
while(recflag)
{
if (datatogo)
{
if (m_File.write(sbuffer,datatogo) == -1)
{
recflag=0; // bail NOW
}
datatogo = 0; // buffer transferred
}
usleep(100); // 100 uS
}
Run Code Online (Sandbox Code Playgroud)
这样做的最终结果是写入磁盘消费者在完成写入时放弃了CPU,知道生产者必须花一些时间来实际填充缓冲区.当消费者在没有数据时睡着了,CPU可供生产者使用.消费者睡眠时间为100 uS,检查数据,如果没有,则返回睡眠状态,因此除了睡眠状态之外,它在该状态下没有做太多事情.
但是,因为睡眠时间是任意的,所以这不可能是最佳的; 即使我仔细调整它以在我的机器上工作(8核,3 GHz),它在另一台机器上的行为也会不同.有时会有数据准备好被写入,消费者刚刚进入睡眠状态,将整个100美元扔出窗外,可以这么说.我也对这种小型计时窗口的分辨率和可靠性有疑虑 - 而较大的窗口将无法工作.
所以.Qt中有多种机制来控制对事物的访问,这基本上就是我想做的事情.但我不明白哪一个(如果有的话)会做我想做的事,这是:
1)让消费者睡眠直到缓冲区已满,然后写入并返回睡眠状态,或直到作业停止,这样它就可以关闭文件(它可以检查唤醒时哪个)
2)当生成器只在缓冲区被写出时才会休眠,否则填充缓冲区并返回生成其内容.
我需要尽可能多的CPU可用 - …