可能的保留周期 - iOS /目标 - C.(Possible Retain Cycle — iOS/Objective - C)
我正在解析XML文件中的数据,并相信我已经找到了一个保留周期。 我不知道如何解决它。 简而言之,我正在解析一个块内的一堆浮动,导致我的内存使用量通过屋顶 - 它超过250 MB。 不好。 这是代码:
[TBXML iterateElementsForQuery:@"library_animations" fromElement:rootElement withBlock:^(TBXMLElement *anElement) { [self parseLibraryAnimationsElement:anElement]; }];
上面的方法调用以下方法:
- (void)parseLibraryAnimationsElement:(TBXMLElement *)element { [TBXML iterateElementsForQuery:@"animation" fromElement:element withBlock:^(TBXMLElement *anElement) { TBXMLElement *extraElement = [TBXML childElementNamed:@"extra" parentElement:anElement]; TBXMLElement *techniqueElement = [TBXML childElementNamed:@"technique" parentElement:extraElement]; // grab float data **NSData *floatData = [self extractFloatArrayFromElement:techniqueElement];** // append data per animation ID NSString *key = [NSString stringWithFormat:@"#%@", [TBXML valueOfAttributeNamed:@"id" forElement:anElement]]; [self.root.sortedAnimationKeys addObject:key]; // use float data to store color information for this frame for (COLLADAMeshGeometry *geometry in self.root.geometries.allValues) { AGLKMesh *mesh = geometry.mesh; NSMutableData *dynamicColorData = [NSMutableData data]; GLKVector3 *newColorInfo = (GLKVector3 *)[floatData bytes]; // cycle through vertices for this mesh and use color float array information for (int i = 0; i < mesh.numberOfVertices; i++) { AGLKMeshVertex *staticVertex = [mesh vertexAtIndex:i]; GLKVector3 newColor = newColorInfo[staticVertex->colorIndex]; GLKVector4 color = GLKVector4Make(newColor.x, newColor.y, newColor.z, 1.0); [dynamicColorData appendBytes:&color length:sizeof(color)]; } // get key and store in animation dictionary on the mesh [mesh.animationBufferDictionary setObject:dynamicColorData forKey:key]; } }]; // sort animation keys if (self.root.sortedAnimationKeys.count > 0) { [self.root.sortedAnimationKeys sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; } }
** ... **之间的方法也在下面。 这是我认为问题所在。 字符串未正确释放。
- (NSData *)extractFloatArrayFromElement:(TBXMLElement *)element { // element is <source> NSMutableData *floatData = [NSMutableData data]; TBXMLElement *floatElement = [TBXML childElementNamed:@"float_array" parentElement:element]; NSString *stringValues = [TBXML textForElement:floatElement]; NSArray *values = [stringValues componentsSeparatedByString:@" "]; for (NSString *value in values) { float floatValue = [value floatValue]; [floatData appendBytes:&floatValue length:sizeof(floatValue)]; } return floatData; }
我说这是在这里的某个地方,因为当我使用Allocations Instrument时,我会得到大量的CFStrings,如下面的截图所示。 我不确定这是否是足够的信息,但如果有人能看到任何问题,请告诉我。 否则,我可以采取正确方向迈出的一步。
当我深入查看CFString(不可变)行时,它有许多行,这些行在
[NSString componentsSeparatedByString:]
中创建。I am parsing data from a XML file and believe I've found a retain cycle. I don't have the best understanding how to fix it though. In short, I'm parsing out a bunch of floats within a block which leads to my memory usage going through the roof - it goes over 250 MB. Not good. Here is the code:
[TBXML iterateElementsForQuery:@"library_animations" fromElement:rootElement withBlock:^(TBXMLElement *anElement) { [self parseLibraryAnimationsElement:anElement]; }];
The method above calls the following method:
- (void)parseLibraryAnimationsElement:(TBXMLElement *)element { [TBXML iterateElementsForQuery:@"animation" fromElement:element withBlock:^(TBXMLElement *anElement) { TBXMLElement *extraElement = [TBXML childElementNamed:@"extra" parentElement:anElement]; TBXMLElement *techniqueElement = [TBXML childElementNamed:@"technique" parentElement:extraElement]; // grab float data **NSData *floatData = [self extractFloatArrayFromElement:techniqueElement];** // append data per animation ID NSString *key = [NSString stringWithFormat:@"#%@", [TBXML valueOfAttributeNamed:@"id" forElement:anElement]]; [self.root.sortedAnimationKeys addObject:key]; // use float data to store color information for this frame for (COLLADAMeshGeometry *geometry in self.root.geometries.allValues) { AGLKMesh *mesh = geometry.mesh; NSMutableData *dynamicColorData = [NSMutableData data]; GLKVector3 *newColorInfo = (GLKVector3 *)[floatData bytes]; // cycle through vertices for this mesh and use color float array information for (int i = 0; i < mesh.numberOfVertices; i++) { AGLKMeshVertex *staticVertex = [mesh vertexAtIndex:i]; GLKVector3 newColor = newColorInfo[staticVertex->colorIndex]; GLKVector4 color = GLKVector4Make(newColor.x, newColor.y, newColor.z, 1.0); [dynamicColorData appendBytes:&color length:sizeof(color)]; } // get key and store in animation dictionary on the mesh [mesh.animationBufferDictionary setObject:dynamicColorData forKey:key]; } }]; // sort animation keys if (self.root.sortedAnimationKeys.count > 0) { [self.root.sortedAnimationKeys sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; } }
The method between ** ... ** is also below. This is where I believe the issue is. The strings aren't being deallocated properly.
- (NSData *)extractFloatArrayFromElement:(TBXMLElement *)element { // element is <source> NSMutableData *floatData = [NSMutableData data]; TBXMLElement *floatElement = [TBXML childElementNamed:@"float_array" parentElement:element]; NSString *stringValues = [TBXML textForElement:floatElement]; NSArray *values = [stringValues componentsSeparatedByString:@" "]; for (NSString *value in values) { float floatValue = [value floatValue]; [floatData appendBytes:&floatValue length:sizeof(floatValue)]; } return floatData; }
I say it's somewhere in here because when I'm using the Allocations Instrument I get a huge number of CFStrings as you can see in the screenshot below. I'm not sure if this is enough information or not, but if someone can see any issues let me know. Otherwise maybe there's a step in the right direction I can take.
When I drill down into the CFString (immutable) line, it has a number of lines that these are created in
[NSString componentsSeparatedByString:]
.
原文:https://stackoverflow.com/questions/19279322
最满意答案
像这样使用
cin.fail()
(而不仅仅是cin >> menuChoice;
)(在这篇文章之后建模):cin >> menuChoice; if (cin.fail()) { cout << "Please enter a valid choice" << endl; cin.clear(); cin.ignore(); continue; } //Remove the cin.ignore() at this place!
有关更多详细信息,请参阅此SO线程
Use
cin.fail()
like this (instead of justcin >> menuChoice;
) (modelled after this post):cin >> menuChoice; if (cin.fail()) { cout << "Please enter a valid choice" << endl; cin.clear(); cin.ignore(); continue; } //Remove the cin.ignore() at this place!
For more detailed info, see this SO thread
相关问答
更多-
TCP/IP模型是一个________。[2023-10-02]
a -
下列中不属于面向对象的编程语言的是?[2022-05-30]
a -
在do-while中输入验证(Input validation in do-while)[2022-04-13]
你的while()条件应该是 while(gradesVector[i] < 0.0 || gradesVector[i] > 100.0)并使用此代码 for(vector::size_type i = 0; i < 15; i++) { int c=0; do { if(c!=0) //checking that we didnt entered loop for first time cout << "Invalid R ... -
在try块中,在你写之前 continue; 但在“您只能输入正数”之后,您应该提示用户输入另一行,并等待用户输入。 “continue”语句跳到循环结束并导致循环的第二部分不运行。 这就是循环无限期运行的原因。 In the try block, before you write continue; but after "You can only type positive numbers," you should prompt the User for another line of input, ...
-
do-while循环没有继续(do-while loop not continuing)[2022-12-05]
while (scan.next() == "Y"); // Is checking for reference equality 在Java中进行对象比较时,使用equals() while (scan.next().equals("Y")); 或者,正如前面的答案指出的那样,您可以将字符与==运算符进行比较 while (scan.next() == "Y"); // Is checking for reference equality When doing object co ... -
问题是“scanf()”可能会在您的输入缓冲区中留下未读数据。 因此,“无限循环”。 另一个问题是你应该从scanf()验证返回值。 如果你期望一个整数值......并且scanf返回“0”项读取...那么你就知道出了什么问题。 这是一个例子: #include
void discard_junk () { char c; while((c = getchar()) != '\n' && c != EOF) ; } int main (int argc, char ... -
测试条件超出了读取它的{和}的范围,因此将String answer的声明(小写)移动到do语句之前,以便我们可以在块之外对其进行测试(while指令不在其中并且是再次执行该块的条件)。 nextLine()返回并消耗相应的值,结果就是它。 String answer; do { System.out.println("Do you want to watch a movie?"); answer = scan.nextLine(); } while(!a ...
-
所以这里有一些代码可以回答你的问题并帮助你入门。 但是,您的逻辑存在问题,这些问题与您之后将要解决的问题无关。 注意 :我在您的代码中添加了注释。 他们中的大多数都以“编辑:”开头,这样你就可以告诉我改变了什么。 我没有在所有情况下都使用这个前缀,因为其中一些是新代码而且显然是我的评论 import java.util.Scanner; public class InterestCalculator { public static void main(String[] args) { // E ...
-
你可以做以下两件事之一: 在while循环结束时添加额外的检查: if(inp>10){ printf("error"); } 或者你可以避免额外的检查,同时牺牲一点可读性并改变你的while循环 while(inp>10 && printf("error")) 这是有效的,因为如果第一个语句为true,则printf()将不会因短路而执行,但如果为false,则printf()将在返回到循环顶部之前执行。 You could do one of two things: Add an extra ...
-
像这样使用cin.fail() (而不仅仅是cin >> menuChoice; )(在这篇文章之后建模): cin >> menuChoice; if (cin.fail()) { cout << "Please enter a valid choice" << endl; cin.clear(); cin.ignore(); continue; } //Remove the cin.ignore() at this place! 有关更多详细信息,请参阅此SO线程 Use cin.fa ...