The test app:
static void Main(string[] args)
{
String connectionString = "DSN=DotNetUltraLightDSII; UID=user; PWD=pass";
String query = "select * from person";
using (OdbcConnection connection = new OdbcConnection(connectionString))
{
connection.Open();
for (Int32 trial = 1; trial <= 100000; trial++)
{
if (0 == trial % 1000)
{
Console.WriteLine("Executing trial #{0:#,0}", trial);
GC.Collect();
}
using (OdbcCommand command = new OdbcCommand(query, connection))
{
using (OdbcDataReader reader = command.ExecuteReader())
{
do
{
while (reader.Read())
{
for (Int32 colIndex = 0; colIndex < reader.FieldCount; colIndex++)
{
Object x = reader[colIndex];
IDisposable d = x as IDisposable;
if (null != d)
{
d.Dispose();
}
d = null;
x = null;
}
}
} while (reader.NextResult());
reader.Close();
}
}
}
connection.Close();
}
Memory usage
Heap Snapshot Comparison
The memory usage just goes up over time. It seems like there are strong handles to the ULPersonTable but I cannot tell what exactly these strong handles are or where they are coming from. We are storing the instances of that type inside gcroot, but they seem to be destroyed. If someone could shed some light on this issue, that would be appreciated.
Regards
Ended up finding the problem. It was a pointer which wasn't being deleted properly.
Related
EDIT: After some more trying and testing, it seems to set down to changing stack size everytime I change code and I want the program to run. If I don't change the stack size, the program seems to crash everytime after code change.
EDIT 2: Same seems to apply to both /HEAP and /STACK
A bit of and odd question, but as far as I can tell, based on some checking and testing.
On multiple projects (at some point) I've come across this same problem:
I change a bit of code, the program crashes.
I change stack size, the program doesn't crash(with the changed code), doesn't seem to matter if incrementing or decrementing stack size.
Seemingly as if there's a hidden randomized stack which, if below a certain value causing the program to crash (no error). I can cause the crash by testing different stack sizes.
On a recent project, the crash seems to "pinpoint" to the bit of code:
typedef unsigned int DINT;
template <typename LIST_ITEM>
struct LIST {
LIST() {
this->length = 0;
this->total = 0;
for (DINT i = 0; i < ENGINE_DATABASE_LIST_LENGTH_MAX; i++) {
//this->item[i] = { 0 };
this->existance[i] = 0;
}
};
~LIST() {
for (DINT i = 0; i < ENGINE_DATABASE_LIST_LENGTH_MAX; i++) {
//this->item[i] = { 0 };
this->existance[i] = 0;
}
this->length = 0;
this->total = 0;
};
DINT length, total;
LIST_ITEM item[ENGINE_DATABASE_LIST_LENGTH_MAX];
DINT existance[ENGINE_DATABASE_LIST_LENGTH_MAX];
DINT _set(LIST_ITEM item) {
for (DINT d = 0; d < ENGINE_DATABASE_LIST_LENGTH_MAX; d++) {
if (this->existance[d] == 0) {
this->item[d] = item;
this->existance[d] = 1;
this->length++;
this->total++;
return d;
}
}
return 0;
}
void _remove(DINT position = 0) {
this->item[position] = {};
this->existance[position] = 0;
LIST <LIST_ITEM> list = {};
DINT length = 0;
do {
if (this->existance[length] == 1) {
list._set(this->_get(length));
this->existance[length] = 0;
//this->item[l] = {};
}
length++;
} while (length < ENGINE_DATABASE_LIST_LENGTH_MAX);
this->_carry(list);
}
LIST_ITEM _get(DINT position = 0) {
return this->item[position];
}
void _carry(LIST <LIST_ITEM> list = {}) {
for (DINT d = 0; d < list.length; d++) {
if (list.existance[d] == 1) this->_set(list.item[d]);
}
}
void _deconstruct() {
/*
for (DINT i = 0; i < ENGINE_DATABASE_LIST_LENGTH_MAX; i++) {
if (this->existance[i] == 1) {
this->existance[i] = 0;
this->item[i] = { };
}
}
this->length = 0;
this->total = 0;
*/
this->~LIST();
}
};
Possible solution/fix:
void _remove(DINT position = 0) {
this->existance[position] = 0;
this->length--;
LIST <LIST_ITEM> *list = new LIST;
for (DINT a = 0; a < ENGINE_DATABASE_LIST_LENGTH_MAX; a++) {
if (this->existance[a] == 1) {
list->_set(this->item[a]);
if (list->length == this->length) break;
}
}
list->total = this->total;
*this = *list;
delete list;
}
If the max list length is set to 64, the program seems to run fine, no matter of stack, but at 128 the crashes start to happen, and if I do the above (change stack size by even just 1, the program runs fine again, until next change of code, then I change stack by 1 again and the program runs fine again).
There might be a "< 0" somewhere (which could also cause crashing), which I just can't seem to spot.
Please do point out.
Seem confusing? Please ask.
My application periodically adds Strings to a List using a Thread. I want to add those strings to a ComboBox as soon as they get added to the List. Is there anyway to bind a ComboBox to a List?
My Code:
static final int max = 20;
List<String> ips = new ArrayList<String>();
public void getIP() throws UnknownHostException {
Task task = new Task<Void>() {
#Override
public Void call() throws UnknownHostException {
InetAddress localhost = InetAddress.getLocalHost();
byte[] ip = localhost.getAddress();
for (int i = 10; i <= max; i++) {
if (isCancelled()) {
break;
}
try {
ip[3] = (byte) i;
InetAddress address = InetAddress.getByAddress(ip);
if (address.isReachable(100)) {
//============================== Populating List ===============//
ips.add(address.getHostName());
}
} catch (Exception e) {
System.err.println(e);
}
updateProgress(i, max);
}
return null;
}
};
//============================== Bind ComboBox to List Code here ===============//
indicator.progressProperty().bind(task.progressProperty());
new Thread(task).start();
}
No there is no way to bind a simple list, since it's not observable. Even with a ObservableList, there would be the problem of the updates coming from a different thread.
You could however use a synchronized list and use the value property to pass the current size, which would allow you to add the items via listener.
Example
This uses a ListView instead of a ComboBox, since the results are visible without user interaction, but you could also use targetList = comboBox.getItems().
#Override
public void start(Stage primaryStage) {
ListView<String> listView = new ListView<>();
List<String> targetList = listView.getItems();
final List<String> ips = Collections.synchronizedList(new ArrayList<>());
Task<Integer> task = new Task<Integer>() {
#Override
protected Integer call() throws Exception {
Random random = new Random();
int size;
for (size = 0; size < 100; size++) {
ips.add(Integer.toString(size));
updateValue(size);
Thread.sleep(random.nextInt(500));
}
return size;
}
};
task.valueProperty().addListener((observable, oldValue, newValue) -> {
// add values not yet in the target list.
for (int i = targetList.size(), newSize = newValue; i < newSize; i++) {
targetList.add(ips.get(i));
}
});
new Thread(task).start();
Scene scene = new Scene(listView);
primaryStage.setScene(scene);
primaryStage.show();
}
It would be a bit simpler though to simply post the updates on the ui thread using Platform.runLater though:
ips = comboBox.getItems();
Task task = new Task<Void>() {
#Override
public Void call() throws UnknownHostException {
InetAddress localhost = InetAddress.getLocalHost();
byte[] ip = localhost.getAddress();
for (int i = 10; i <= max; i++) {
if (isCancelled()) {
break;
}
try {
ip[3] = (byte) i;
InetAddress address = InetAddress.getByAddress(ip);
if (address.isReachable(100)) {
//============================== Populating List ===============//
final String hostName = address.getHostName();
// do update on application thread
Platform.runLater(() -> ips.add(hostName));
}
} catch (Exception e) {
System.err.println(e);
}
updateProgress(i, max);
}
return null;
}
};
i suggest you to do the following:
change
List<String> ips = new ArrayList<String>();
to
final ObservableList<String> ips = FXCollections.observableArrayList();
change:
Task task = new Task<Void>()
to
Task<ObservableList<String> task = new Task<>(){
#Override
public ObservableList<String> call() throws UnknownHostException {
...
return ips;
}
};
comboBox.itemsProperty().bind(task.valueProperty());
Hopefully someone can help me with this issue. I'm trying to couple an IEnumerator with my object pooling script to instantiate enemies in waves. But I can't get them to instantiate without immediately destroying themselves 2 or 3 times and then instantiating one wave of enemies and never spawning again. Can anyone help me see where I'm going wrong here?
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class SpawnMaster : MonoBehaviour {
public int enemyCount = 4;
public float spawnWait=0.5f;
public float startWait=1;
public float waveWait=3;
public Transform[] spawnPoints;
private int currentWave = 0;
private int waveCount = 10;
private IEnumerator spawnWaves;
private IEnumerator goHorde;
bool isSpawning = false;
void Update()
{
if(!isSpawning)
{
isSpawning = true;
StartCoroutine(SpawnWaves(currentWave));
}
}
IEnumerator SpawnWaves (int currentWave)
{
Debug.Log("Spawning " + currentWave + "currentWave");
for (int i = 0; i < waveCount; i++)
{
StartCoroutine(GoHorde());
}
currentWave += 1;
yield return new WaitForSeconds (waveWait);
//We've spawned, so start another spawn
isSpawning = false;
}
IEnumerator GoHorde()
{
GameObject beetle01 = BeetlePool.current.GetPooledObject();
if(beetle01 == null)
yield return null;
// Only pick a new spawn point once per wave
int spawnPointIndex = Random.Range (0, spawnPoints.Length);
for (int j = 0; j < enemyCount; j++)
{
beetle01.transform.position = spawnPoints[spawnPointIndex].position;
beetle01.transform.rotation = spawnPoints[spawnPointIndex].rotation;
beetle01.SetActive(true);
yield return new WaitForSeconds (spawnWait);
}
}
}
I would change:
if(!isSpawning)
to:
if(isSpawning != true)
Or:
if(isSpawning == false)
Also if you are going to have multiple waves of enemies that are being instantiated and destroyed. You should look into object pooling to save memory.
I've this piece of code, which is called by a timer Update mechanism.
However, I notice, that the memory size of the application, while running, continuously increases by 4, indicating that there might be a rogue pointer, or some other issue.
void RtdbConnection::getItemList()
{
std::vector<CString> tagList = mItemList->getItems();
//CString str(_T("STD-DOL1"));
PwItemList* pil = mPwSrv->GetItemList();
CPwItem pw ;
for(auto it = tagList.begin(); it != tagList.end(); ++it)
{
pw = mPwSrv->GetItem(*it);
pil->AddItem(&(PwItem)pw);
}
pil->AddInfo(DB_DESC); //Description
pil->AddInfo(DB_QALRM); // Alarm Status
pil->AddInfo(DB_QUNAK); //UNACK status
pil->AddInfo(DB_AL_PRI); // Priority of the alarm tag
pil->ExecuteQuery();
int i = 0;
for (auto it = tagList.begin(); i < pil->GetInfoRetrievedCount() && it != tagList.end(); i+=4, it++)
{
//item = {0};
CString str(*it);
PwInfo info = pil->GetInfo(i);
CString p(info.szValue().c_str());
bool isAlarm = pil->GetInfo(i+1).bValue();
bool isAck = pil->GetInfo(i+2).bValue();
int priority = pil->GetInfo(i+3).iValue();
item = ItemInfo(str, p, isAlarm, isAck, priority);
//int r = sizeof(item);
mItemList->setInfo(str, item); // Set the details for the item of the List
}
delete pil;
pil = NULL;
}
I cannot seem to find a memory block requiring de-allocation here. Nor is there any allocation of memory when I step inside the following function :
mItemList->setInfo(str, item);
which is defined as :
void ItemList::setInfo(CString tagname, ItemInfo info)
{
int flag = 0;
COLORREF tempColour;
std::map<CString, ItemInfo>::iterator tempIterator;
if ( (tempIterator = mAlarmListMap.find(tagname)) !=mAlarmListMap.end() )
{
//remove the current iteminfo and insert new one
if(mAlarmListMap[tagname].getPriority() != info.getPriority() && (mAlarmListMap[tagname].getPriority()!=0))
{
mAlarmListMap[tagname].updatePriority(info.getPriority());
mAlarmListMap[tagname].mPrioChanged = TRUE;
}
else
{
mAlarmListMap[tagname].mPrioChanged = FALSE;
((mAlarmListMap[tagname].getPrevPriority() != 0)?(mAlarmListMap[tagname].ResetPrevPriority()):TRUE);
mAlarmListMap[tagname].setPriority(info.getPriority());
}
mAlarmListMap[tagname].setDescription(info.getDescription());
mAlarmListMap[tagname].setAlarm(info.getAlarmStat());
mAlarmListMap[tagname].setAlarmAck(info.getAckStat());
tempColour = mColourLogic->setUpdatedColour(mAlarmListMap[tagname].getAlarmStat(), mAlarmListMap[tagname].getAckStat(), flag);
mAlarmListMap[tagname].setColour(tempColour);
if(!(info.getAlarmStat() || info.getAckStat()))
{
flag = 1;
mAlarmListMap[tagname].mIsRTN = true;
mAlarmListMap[tagname].setDisplayCondition(false);
}
else
{
mAlarmListMap[tagname].setDisplayCondition(true);
}
//((mAlarmListMap[tagname].mIsRTN == true)?
}
else
{
tempIterator = mAlarmListMap.begin();
tempColour = mColourLogic->fillColourFirst(info.getAlarmStat(), info.getAckStat());
info.setColour(tempColour);
mAlarmListMap.insert(tempIterator, std::pair<CString,ItemInfo>(tagname,info));
}
}
I tried juggling with the allocations, but the increase is always a constant 4.
Could anyone kindly look and highlight where the issue could be?
Thanks a lot.
When I run the program and new a NetworkEditor, it will corrupt at the constructor because of it reads out of the array's memory.
When I debug it one loop by one loop, it will be ok!?
Why? Didn't it allocate enough memory for the array before it entered the constructor?
In my class, I have two properties:
/*NetworkEditor.h*/
class CNetworkEditor : public CDiagramEditor
{...
VLLink* VL_list[10];
VLLink* temp_VL_list[10];
}
and in the constructor, I initialize the arraies:
/*NetworkEditor.cpp*/
for (int i = 0; i < 10; i++)
{
VLLink* vl_link = NULL;
while(vl_link == NULL)
{
vl_link = new VLLink;
}
vl_link->preLink = NULL;
vl_link->nextLink = NULL;
vl_link->link = NULL;
VLLink* vl_link2 = NULL;
while (vl_link2 == NULL)
{
vl_link2 = new VLLink;
}
vl_link2->preLink = NULL;
vl_link2->nextLink = NULL;
vl_link2->link = NULL;
VL_list[i] = vl_link;
temp_VL_list[i] = vl_link2;
}
and VLLink is defined as:
typedef struct struct_VLLink
{
CPhysicalLink* link;
struct_VLLink* preLink;
struct_VLLink* nextLink;
}VLLink;
If I change it to:
VLLink* VL_list2[10];
VLLink* temp_VL_list2[10];
for (int i = 0; i < MAX_VL_NUM; i++)
{
VLLink* vl_link = NULL;
while(vl_link == NULL)
{
vl_link = new VLLink;
}
vl_link->preLink = NULL;
vl_link->nextLink = NULL;
vl_link->link = NULL;
VLLink* vl_link2 = NULL;
while (vl_link2 == NULL)
{
vl_link2 = new VLLink;
}
vl_link2->preLink = NULL;
vl_link2->nextLink = NULL;
vl_link2->link = NULL;
VL_list2[i] = vl_link;
temp_VL_list2[i] = vl_link2;
}
It will be ok!?
Apart from #PeterHuene's suggestion to replace VL_list and temp_VL_list with something like std::list<CPhysicalLink> or similar, you should move the initialization of VLLink into the constructor, avoiding the code duplication in your loop
struct VLLink {
VLLink() : link(NULL), prelink(NULL), nextlink(NULL) {}
...
};`
then you can reduce your loop as #MikeSeymour said
for (int i = 0; i < MAX_VL_NUM; i++) {
VL_list[i] = new VLLink();
temp_VL_list[i] = new VLLink();
}
A reason for your memory problem might be, that MAX_VL_NUM is larger than 10. So, you should either use MAX_VL_NUM everywhere or use 10 everywhere.
And now to your question ;-)
If I change it to ... It will be ok!?
Nobody can answer this, because nobody knows what you want to achieve. My first reaction would be definitely No!, because moving variables around "just because" is almost always a bad idea. It's better to analyze the problem and fix the cause than to cure some random symptoms.
Your change would also modify the meaning from member of a class to automatic variable on the stack.