AddressSanitizer warnings memory leaks occured when repeating connecting/disconnecting to a db with msodbcsql for linux both 17.10 and 18.1.
 
This may be same issue as this comment https://techcommunity.microsoft.com/t5/sql-server-blog/odbc-driver-17-6-for-sql-server-released/bc-p/1954999/highlight/true#M1658 .
I have a reproduction code. 
 
 
My program repeats connecting and disconnecting to a db server.
 
pseud code
AllocHandle(hEnv)
AllocHandle(hDbc)
repeat N
  Connect(hDbc)
  Disconnect(hDbc)
FreeHandle(hDbc)
FeeHandle(hEnv)
When N > 1, AddressSanitizer outputs memory leak detections.
 
Also I tried like below and got same warnings.
repeat N
  AllocHandle(hEnv)
  AllocHandle(hDbc)
  Connect(hDbc)
  Disconnect(hDbc)
  FreeHandle(hDbc)
  FeeHandle(hEnv)
 
I want to know this is a false-positive detection or not.
Or, is there a workaround ?
 
Thank you.
 
The details are listed below.
 
Environment
OracleLinux 8.6
GCC11 with AddressSanitizer
 
Packages
 
$ dnf list --installed | grep gcc
gcc-toolset-11-binutils.x86_64          2.36.1-2.0.1.el8                                  @ol8_appstream              
gcc-toolset-11-gcc.x86_64               11.2.1-9.1.0.2.el8                                @ol8_appstream              
gcc-toolset-11-gcc-c++.x86_64           11.2.1-9.1.0.2.el8                                @ol8_appstream              
gcc-toolset-11-libasan-devel.x86_64     11.2.1-9.1.0.2.el8                                @ol8_appstream              
gcc-toolset-11-libstdc++-devel.x86_64   11.2.1-9.1.0.2.el8                                @ol8_appstream              
gcc-toolset-11-runtime.x86_64           11.1-1.el8                                        @ol8_appstream              
libgcc.x86_64                           8.5.0-10.1.0.1.el8_6                              @System       
$ dnf list --installed | grep unixODBC
unixODBC.x86_64                         2.3.7-1.rh                                        @packages-microsoft-com-prod
unixODBC-devel.x86_64                   2.3.7-1.rh                                        @packages-microsoft-com-prod
$ dnf list --installed | grep msodbc
msodbcsql17.x86_64                      17.10.1.1-1                                       @packages-microsoft-com-prod
msodbcsql18.x86_64                      18.1.2.1-1                                        @packages-microsoft-com-prod
 
 
SourceCode
main.c
rewrite L56 when using.
#include <msodbcsql.h>
#include <sql.h>
#include <sqlext.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
void HandleDiagnosticRecord(SQLHANDLE hHandle, SQLSMALLINT hType, RETCODE RetCode) {
  SQLSMALLINT iRec = 0;
  SQLINTEGER iError;
  char wszMessage[1000];
  char wszState[SQL_SQLSTATE_SIZE + 1];
 
  if (RetCode == SQL_INVALID_HANDLE) {
    fprintf(stderr, "Invalid handle!\n");
    return;
  }
 
  while (SQLGetDiagRec(hType, hHandle, ++iRec, wszState, &iError, wszMessage,
                       (SQLSMALLINT)(sizeof(wszMessage) / sizeof(char)), (SQLSMALLINT *)NULL) == SQL_SUCCESS) {
    // Hide data truncated..
    if (strncmp(wszState, "01004", 5)) {
      fprintf(stderr, "[%5.5s] %s (%d)\n", wszState, wszMessage, iError);
    }
  }
}
 
#define TRYODBC(h, ht, x)                   \
  {                                         \
    RETCODE rc = x;                         \
    if (rc != SQL_SUCCESS) {                \
      HandleDiagnosticRecord(h, ht, rc);    \
    }                                       \
    if (rc == SQL_ERROR) {                  \
      fprintf(stderr, "Error in " #x "\n"); \
      goto Exit;                            \
    }                                       \
  }
 
int main(void) {
  SQLHENV hEnv = NULL;
  SQLHDBC hDbc = NULL;
 
  if (SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv) == SQL_ERROR) {
    fprintf(stderr, "Unable to allocate an environment handle\n");
    exit(-1);
  }
 
  TRYODBC(hEnv, SQL_HANDLE_ENV, SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0));
 
  TRYODBC(hEnv, SQL_HANDLE_ENV, SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc));
 
  const int LOOP = 2;  // (LOOP - 1) * 24byte direct leak detected
  for (int i = 0; i < LOOP; i++) {
    const char *connStr = "CONNECTION STRING";
    TRYODBC(hDbc, SQL_HANDLE_DBC,
            SQLDriverConnect(hDbc, NULL, (SQLCHAR *)connStr, strlen(connStr), NULL, 0, NULL, SQL_DRIVER_NOPROMPT));
 
    printf("Connected!\n");
 
    TRYODBC(hDbc, SQL_HANDLE_DBC, SQLDisconnect(hDbc));
 
    printf("Disconnected\n");
  }
 
Exit:
  if (hDbc) {
    SQLDisconnect(hDbc);
    SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
    hDbc = NULL;
  }
 
  if (hEnv) {
    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
    hEnv = NULL;
  }
  return 0;
}
 
build and run 
$ gcc main.c -std=c11 -I/opt/microsoft/msodbcsql18/include -lodbc -g -O0 -fsanitize=address -lasan -o main.o
$ ./main.o
[01000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Changed database context to 'master'. (5701)
[01000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Changed language setting to us_english. (5703)
Connected!
Disconnected
[01000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Changed database context to 'master'. (5701)
[01000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Changed language setting to us_english. (5703)
Connected!
Disconnected
 
=================================================================
==1103==ERROR: LeakSanitizer: detected memory leaks
 
Direct leak of 24 byte(s) in 1 object(s) allocated from:
    #0 0x7f8f00b21307 in operator new(unsigned long) (/lib64/libasan.so.6+0xb6307)
    #1 0x7f8efbb5b2ca  (/opt/microsoft/msodbcsql18/lib64/libmsodbcsql-18.1.so.2.1+0x1822ca)
 
Indirect leak of 88 byte(s) in 1 object(s) allocated from:
    #0 0x7f8f00b21307 in operator new(unsigned long) (/lib64/libasan.so.6+0xb6307)
    #1 0x7f8efbae3379  (/opt/microsoft/msodbcsql18/lib64/libmsodbcsql-18.1.so.2.1+0x10a379)
 
SUMMARY: AddressSanitizer: 112 byte(s) leaked in 2 allocation(s).