2013-09-13 5 views
-1

У меня есть простая программа Cocoa для построения данных, считываемых с сервера на основе малины Pi. После нескольких тысяч чтений, использование памяти в программной памяти приближается к 1 ГБ. Каждое чтение просто получает длинное целое число за время и значение поплавка, представляющее температуру, считанную от датчика температуры. Я удалил все, что мог подумать, что может использовать память, и проблема не меняется. Пожалуйста, скажите мне, где моя проблема.Помогите найти утечку памяти

// 
    // 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 
+1

Вы хотите, чтобы мы просмотрели все *, что *? – trojanfoe

+2

И выполняете свою работу?))) –

+1

Peter, ЕСЛИ авария связана с выпуском или сохранением объекта, то я хотел бы сказать, пожалуйста, включите зомби в настройке xcode (внутри левой верхней схемы редактирования внутри, что вы получите вариант). После того, как вы включите его, вам будет полезно проанализировать крах –

ответ

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]; 
} 
+0

Использование инструментов и наблюдение за сбором NSBezierPaths могло бы найти его гораздо менее болезненно. –

+0

Я не знаком с этим. Я сделаю некоторые исследования по этому вопросу. Спасибо! –

Смежные вопросы