我有一个简单的 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