-1

我有一个简单的 Cocoa 程序来绘制从基于 Raspberry Pi 的服务器读取的数据。几千次读取后,程序内存使用量将推向 1 GB。每次读取都只是获得一个长整数时间和一个浮点值,表示从温度传感器读取的温度。我已经删除了我能想到的可能会利用内存的所有内容,并且问题没有改变。请告诉我我的问题在哪里。

    //
    //  ABSAppDelegate.m
   //  RPi_socket_test   
   //

   #import "ABSAppDelegate.h"
   #include <sys/socket.h> 
   #include <sys/types.h>
   #include <netinet/in.h>
   #include <netdb.h>
   #include <stdio.h>
   #include <string.h>
   #include <stdlib.h>
   #include <unistd.h>
   #include <errno.h>
   #include <arpa/inet.h>

@implementation ABSAppDelegate

- (void)dealloc
{
[super dealloc];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
NSView *superview = [[self window] contentView];

NSRect fullPlotFrame = [[self window] frame];
fullPlotFrame.size.height *= 0.75;
fullPlotFrame.size.width *= 0.85;
fullPlotFrame.origin.x = [[self window] frame].size.width*0.1;
fullPlotFrame.origin.y = [[self window] frame].size.height*0.02;

thePlot = [[[RPiViewController alloc] initWithFrame:fullPlotFrame] retain];
[superview addSubview:thePlot];
[thePlot display];

[NSThread detachNewThreadSelector:@selector(getTemp) toTarget:self withObject:nil];

}

-(void)getTemp{

int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;

while(ok){
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    memset(recvBuff, '0',sizeof(recvBuff));
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        NSLog(@"\n Error : Could not create socket \n");
        ok = false;
    }

    memset(&serv_addr, '0', sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5001);

    if(inet_pton(AF_INET, "172.27.220.44", &serv_addr.sin_addr)<=0)
    {
        NSLog(@"\n inet_pton error occured\n");
    }

    if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        NSLog(@"\n Error : Connect Failed \n");
        ok = false;
    }

    while ( (n = (int)read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
    {
        recvBuff[n] = '\0';
        [self performSelectorOnMainThread:@selector(displayTemp:) withObject:[NSString stringWithFormat:@"%.18s", recvBuff] waitUntilDone:YES];
    }

    if(n < 0)
    {
        NSLog(@"\n Read error \n");
    }
    close(sockfd);
    sleep(1);
    [pool drain];
}

}

-(void)displayTemp:(NSString*)theData{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSPoint pointForConversion = NSPointFromString(theData);
[txtTempC setStringValue:[NSString stringWithFormat:@"%0.0f, %0.2f", pointForConversion.x, pointForConversion.y]];

long int dataSize = [thePlot SizeOfData];
if(dataSize < 1024) [txtSizeOfData setStringValue:[NSString stringWithFormat:@"%i Bytes", (int)dataSize]];
  else if(dataSize < 1024*1024) [txtSizeOfData setStringValue:[NSString stringWithFormat:@"%0.3f kBytes", (float)dataSize/1024]];
         else [txtSizeOfData setStringValue:[NSString stringWithFormat:@"%0.3f MBytes", (float)dataSize/(1024*1024)]];

[thePlot addDataToPlot:pointForConversion];
[thePlot display];
[[self window] display];

[pool drain];
}

-(IBAction)getTemp:(id)sender{
if(!ok){
    ok = true;
    [NSThread detachNewThreadSelector:@selector(getTemp) toTarget:self withObject:nil];
}
}

-(IBAction)stopClient:(id)sender{
ok = false;
}

-(void)controlTextDidChange:(NSNotification *)obj{
if([obj object] == txtMax) [thePlot setMaxRawPlotData:(int)[txtMax integerValue]];
}

@end

带视图控制器

    //
   //  RPiViewController.m
   //  RPi_socket_test
   //

  #import "RPiViewController.h"

  @implementation RPiViewController

  - (id)initWithFrame:(NSRect)frame
 {
self = [super initWithFrame:frame];
if (self) {
    // Initialization code here.
    fontSize = 10;

    NSMutableDictionary *drawStringAttributes = [[NSMutableDictionary alloc] init];
    [drawStringAttributes setValue:[NSColor blackColor] forKey:NSForegroundColorAttributeName];
    NSFont *myFont = [NSFont fontWithName:@"American Typewriter" size:fontSize];
    [drawStringAttributes setValue:myFont forKey:NSFontAttributeName];

    NSString* strLabelWidth = [NSString stringWithFormat:@"%0.2f", 55.55];
    float labelWidth = [strLabelWidth sizeWithAttributes:drawStringAttributes].width;

    NSRect frameForData = [self bounds];
    frameForData.origin.x += labelWidth;
    frameForData.size.width -= labelWidth;

    myPlot = [[[RPiView alloc] initWithFrame:frameForData] retain];

    [self addSubview:myPlot];
}

return self;
}

- (void)drawRect:(NSRect)dirtyRect
{
// Drawing code here.

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSPoint minPoint = [myPlot findMinValues];
NSPoint maxPoint = [myPlot findMaxValues];

NSMutableDictionary *drawStringAttributes = [[NSMutableDictionary alloc] init];
[drawStringAttributes setValue:[NSColor blackColor] forKey:NSForegroundColorAttributeName];
NSFont *myFont = [NSFont fontWithName:@"American Typewriter" size:fontSize];
[drawStringAttributes setValue:myFont forKey:NSFontAttributeName];

NSString* MinTempLabel = [NSString stringWithFormat:@"%0.2f", minPoint.y];
NSPoint pointToDrawLabel = {0,0};
[MinTempLabel drawAtPoint:pointToDrawLabel withAttributes:drawStringAttributes];

NSString* MaxTempLabel = [NSString stringWithFormat:@"%0.2f", maxPoint.y];
pointToDrawLabel.y = [self bounds].size.height - [MaxTempLabel sizeWithAttributes:drawStringAttributes].height;
[MaxTempLabel drawAtPoint:pointToDrawLabel withAttributes:drawStringAttributes];

[pool drain];
}

-(void)addDataToPlot:(NSPoint)theDataToPlot{
[myPlot addDataToPlot:theDataToPlot];
}


-(long int)SizeOfData{
long int dataSize = [myPlot SizeOfData];

return dataSize;
}

-(int)setMaxRawPlotData:(int)theMax{
 return [myPlot setMaxRawPlotData:theMax];
 }

 @end

和子视图控制器

     //
     //  RPiView.m
     //  RPi_socket_test
     //

     #import "RPiView.h"

     @implementation RPiView

     - (id)initWithFrame:(NSRect)frame
     {
self = [super initWithFrame:frame];
if (self) {
    // Initialization code here.
    maxRawPlotData = 3600;
    firstRawPlotIndex = 0;
    dataCount = 0;
}

return self;
}

  - (void)drawRect:(NSRect)dirtyRect
  {    // Drawing code here.
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

NSPoint minPoint = [self findMinValues];
NSPoint maxPoint = [self findMaxValues];

float xScale = ([self bounds].size.width)/(maxPoint.x - minPoint.x);
float yScale = [self bounds].size.height/(maxPoint.y - minPoint.y);

[[NSColor whiteColor] set];
NSRect fillArea = [self bounds];
[NSBezierPath fillRect:fillArea];


NSBezierPath *pathForPlot = [[NSBezierPath alloc] init];
if(dataCount<maxRawPlotData){
    if(dataCount>1){
        NSPoint p1 = myData[0];
        p1.x = (p1.x-minPoint.x)*xScale;
        p1.y = (p1.y-minPoint.y)*yScale;
        [pathForPlot moveToPoint:p1];
    }
    for(int i=1; i<dataCount; i++){
        NSPoint p = myData[i];
        p.x = (p.x-minPoint.x)*xScale;
        p.y = (p.y-minPoint.y)*yScale;
        [pathForPlot lineToPoint:p];
    }
}
else{
    unsigned long firstPointToPlot = dataCount-maxRawPlotData;
    NSPoint p1 = myData[firstPointToPlot];
    xScale = [self bounds].size.width/maxRawPlotData;
    minPoint.x = p1.x;
    p1.x = (p1.x-minPoint.x)*xScale;
    p1.y = (p1.y-minPoint.y)*yScale;
    [pathForPlot moveToPoint:p1];
    for(unsigned long i=firstPointToPlot; i<dataCount; i++){
        NSPoint p = myData[i];
        p.x = (p.x-minPoint.x)*xScale;
        p.y = (p.y-minPoint.y)*yScale;
        [pathForPlot lineToPoint:p];
    }
}
[[NSColor blackColor] set];
[pathForPlot stroke];

[pool drain];
}

-(void)addDataToPlot:(NSPoint)theDataToPlot{
myData[dataCount] = theDataToPlot;
dataCount++;
 }

-(NSPoint)findMaxValues{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

NSPoint maxValue = {-1e9, -1e9};

for(int i=0; i<dataCount; i++){
    NSPoint testValue = myData[i];
    if(testValue.x > maxValue.x) maxValue.x = testValue.x;
    if(testValue.y > maxValue.y) maxValue.y = testValue.y;
}
[pool drain];
return maxValue;
}

-(NSPoint)findMinValues{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

NSPoint maxValue = {1e9, 1e9};

for(int i=0; i<dataCount; i++){
    NSPoint testValue = myData[i];
    if(testValue.x < maxValue.x) maxValue.x = testValue.x;
    if(testValue.y < maxValue.y) maxValue.y = testValue.y;
}
[pool drain];
return maxValue;
}

-(long int)SizeOfData{
long int dataSize = 0;
for(int i=0; i<dataCount; i++){
    dataSize += sizeof(NSPoint);
}

return dataSize;
}

-(int)setMaxRawPlotData:(int)theMax{
if(theMax<10) theMax = 10;
maxRawPlotData = theMax;
return (int)dataCount;
}

@end
4

1 回答 1

0

因此,在痛苦地逐段关闭代码之后,我在子视图控制器中跟踪到 drawRect 方法的泄漏。通过在我可以添加的任何地方添加 NSAutoreleasePools 并释放 NSBezierPath,泄漏被堵住了。

感谢您给我一个“大声思考”的机会!

- (void)drawRect:(NSRect)dirtyRect
 {    // Drawing code here.
 NSAutoreleasePool* uberpool = [[NSAutoreleasePool alloc] init];

NSPoint minPoint = [self findMinValues];
NSPoint maxPoint = [self findMaxValues];

float xScale = ([self bounds].size.width)/(maxPoint.x - minPoint.x);
float yScale = [self bounds].size.height/(maxPoint.y - minPoint.y);

[[NSColor whiteColor] set];
NSRect fillArea = [self bounds];
[NSBezierPath fillRect:fillArea];

NSBezierPath *pathForPlot = [[NSBezierPath alloc] init];
if(dataCount<maxRawPlotData){
    if(dataCount>1){
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

        NSPoint p1 = myData[0];
        p1.x = (p1.x-minPoint.x)*xScale;
        p1.y = (p1.y-minPoint.y)*yScale;
        [pathForPlot moveToPoint:p1];

        [pool drain];
    }
    for(int i=1; i<dataCount; i++){
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

        NSPoint p = myData[i];
        p.x = (p.x-minPoint.x)*xScale;
        p.y = (p.y-minPoint.y)*yScale;
        [pathForPlot lineToPoint:p];

        [pool drain];
    }
}
else{
    unsigned long firstPointToPlot = dataCount-maxRawPlotData;
    NSPoint p1 = myData[firstPointToPlot];
    xScale = [self bounds].size.width/maxRawPlotData;
    minPoint.x = p1.x;
    p1.x = (p1.x-minPoint.x)*xScale;
    p1.y = (p1.y-minPoint.y)*yScale;
    [pathForPlot moveToPoint:p1];
    for(unsigned long i=firstPointToPlot; i<dataCount; i++){
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

        NSPoint p = myData[i];
        p.x = (p.x-minPoint.x)*xScale;
        p.y = (p.y-minPoint.y)*yScale;
        [pathForPlot lineToPoint:p];

        [pool drain];
    }
}
[[NSColor blackColor] set];
[pathForPlot stroke];

[pathForPlot release];
[uberpool drain];
}
于 2013-09-13T23:51:06.337 回答